~drizzle-trunk/drizzle/development

660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1
/* Copyright (C) 2000-2006 MySQL AB
1 by brian
clean slate
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
17
/**
18
  @file
19
20
  @brief
21
  Sorts a database
22
*/
23
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
24
#include "config.h"
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
25
26
#include <float.h>
1241.9.59 by Monty Taylor
Removed the first mystrings header.
27
#include <limits.h>
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
28
29
#include <queue>
30
#include <algorithm>
31
1237.9.2 by Padraig O'Sullivan
Moved opt_range.[cc,h] into the optimizer directory and namespace and renamed the files to
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"
1237.9.4 by Padraig O'Sullivan
Removed the inclusion of drizzled/field.h in the server_includes header file.
39
#include "drizzled/records.h"
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
40
#include "drizzled/internal/iocache.h"
41
#include "drizzled/internal/my_sys.h"
1241.9.62 by Monty Taylor
Removed plugin/myisam/myisam.h from session.h
42
#include "plugin/myisam/myisam.h"
1273.1.15 by Jay Pipes
This patch completes the first step in the splitting of
43
#include "drizzled/plugin/transactional_storage_engine.h"
1 by brian
clean slate
44
897.1.6 by Padraig
Cleaning up merge_buffers() function a little bit.
45
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
46
47
namespace drizzled
48
{
897.1.6 by Padraig
Cleaning up merge_buffers() function a little bit.
49
520.7.1 by Monty Taylor
Moved hash.c to drizzled.
50
/* functions defined in this file */
1 by brian
clean slate
51
438.1.13 by Brian Aker
uint cleanup.
52
static char **make_char_array(char **old_pos, register uint32_t fields,
641.3.7 by Monty Taylor
More my_malloc removal.
53
                              uint32_t length);
1237.9.2 by Padraig O'Sullivan
Moved opt_range.[cc,h] into the optimizer directory and namespace and renamed the files to
54
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
55
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffer_file,
56
                                             uint32_t count,
57
                                             unsigned char *buf);
1237.9.2 by Padraig O'Sullivan
Moved opt_range.[cc,h] into the optimizer directory and namespace and renamed the files to
58
1578.4.11 by Brian Aker
PAss through the code removing current_session
59
static ha_rows find_all_keys(Session *session,
60
                             SORTPARAM *param,
1237.13.3 by Padraig O'Sullivan
Performed numerous style cleanups in range.[cc,h].
61
                             optimizer::SqlSelect *select,
1237.9.2 by Padraig O'Sullivan
Moved opt_range.[cc,h] into the optimizer directory and namespace and renamed the files to
62
			     unsigned char * *sort_keys, 
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
63
                             internal::IO_CACHE *buffer_file,
64
			     internal::IO_CACHE *tempfile,
65
                             internal::IO_CACHE *indexfile);
66
67
static int write_keys(SORTPARAM *param,
68
                      unsigned char * *sort_keys,
69
		      uint32_t count,
70
                      internal::IO_CACHE *buffer_file,
71
                      internal::IO_CACHE *tempfile);
72
73
static void make_sortkey(SORTPARAM *param,
74
                         unsigned char *to,
75
                         unsigned char *ref_pos);
1 by brian
clean slate
76
static void register_used_fields(SORTPARAM *param);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
77
static int merge_index(SORTPARAM *param,
78
                       unsigned char *sort_buffer,
1 by brian
clean slate
79
		       BUFFPEK *buffpek,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
80
		       uint32_t maxbuffer,
81
                       internal::IO_CACHE *tempfile,
82
		       internal::IO_CACHE *outfile);
83
static bool save_index(SORTPARAM *param,
84
                       unsigned char **sort_keys,
85
                       uint32_t count,
327.2.3 by Brian Aker
Refactoring of class Table
86
                       filesort_info_st *table_sort);
438.1.13 by Brian Aker
uint cleanup.
87
static uint32_t suffix_length(uint32_t string_length);
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
88
static uint32_t sortlength(Session *session,
89
                           SORT_FIELD *sortorder,
90
                           uint32_t s_length,
91
                           bool *multi_byte_charset);
92
static SORT_ADDON_FIELD *get_addon_fields(Session *session,
93
                                          Field **ptabfield,
94
                                          uint32_t sortlength,
95
                                          uint32_t *plength);
1 by brian
clean slate
96
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
481 by Brian Aker
Remove all of uchar.
97
                                unsigned char *buff);
1 by brian
clean slate
98
/**
99
  Sort a table.
100
  Creates a set of pointers that can be used to read the rows
101
  in sorted order. This should be done with the functions
102
  in records.cc.
103
104
  Before calling filesort, one must have done
105
  table->file->info(HA_STATUS_VARIABLE)
106
107
  The result set is stored in table->io_cache or
108
  table->record_pointers.
109
520.1.22 by Brian Aker
Second pass of thd cleanup
110
  @param session           Current thread
1 by brian
clean slate
111
  @param table		Table to sort
112
  @param sortorder	How to sort the table
113
  @param s_length	Number of elements in sortorder
114
  @param select		condition to apply to the rows
115
  @param max_rows	Return only this many rows
116
  @param sort_positions	Set to 1 if we want to force sorting by position
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
117
			(Needed by UPDATE/INSERT or ALTER Table)
1 by brian
clean slate
118
  @param examined_rows	Store number of examined rows here
119
120
  @todo
121
    check why we do this (param.keys--)
122
  @note
123
    If we sort by position (like if sort_positions is 1) filesort() will
124
    call table->prepare_for_position().
125
126
  @retval
127
    HA_POS_ERROR	Error
128
  @retval
129
    \#			Number of rows
130
  @retval
131
    examined_rows	will be set to number of examined rows
132
*/
133
520.1.22 by Brian Aker
Second pass of thd cleanup
134
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
1237.13.3 by Padraig O'Sullivan
Performed numerous style cleanups in range.[cc,h].
135
		 optimizer::SqlSelect *select, ha_rows max_rows,
1 by brian
clean slate
136
                 bool sort_positions, ha_rows *examined_rows)
137
{
138
  int error;
308 by Brian Aker
ulong conversion
139
  uint32_t memavl, min_sort_memory;
438.1.13 by Brian Aker
uint cleanup.
140
  uint32_t maxbuffer;
1 by brian
clean slate
141
  BUFFPEK *buffpek;
142
  ha_rows records= HA_POS_ERROR;
481 by Brian Aker
Remove all of uchar.
143
  unsigned char **sort_keys= 0;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
144
  internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
1 by brian
clean slate
145
  SORTPARAM param;
146
  bool multi_byte_charset;
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
147
327.2.3 by Brian Aker
Refactoring of class Table
148
  filesort_info_st table_sort;
327.2.4 by Brian Aker
Refactoring table.h
149
  TableList *tab= table->pos_in_table_list;
1 by brian
clean slate
150
  Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
151
1532.1.15 by Brian Aker
Partial encapsulation of TableShare from Table.
152
  DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1 by brian
clean slate
153
154
  /*
155
   Release InnoDB's adaptive hash index latch (if holding) before
156
   running a sort.
157
  */
1273.1.15 by Jay Pipes
This patch completes the first step in the splitting of
158
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
1 by brian
clean slate
159
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
160
  /*
161
    Don't use table->sort in filesort as it is also used by
1237.13.5 by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files.
162
    QuickIndexMergeSelect. Work with a copy and put it back at the end
1 by brian
clean slate
163
    when index_merge select has finished with it.
164
  */
327.2.3 by Brian Aker
Refactoring of class Table
165
  memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
1 by brian
clean slate
166
  table->sort.io_cache= NULL;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
167
1 by brian
clean slate
168
  outfile= table_sort.io_cache;
169
  my_b_clear(&tempfile);
170
  my_b_clear(&buffpek_pointers);
171
  buffpek=0;
172
  error= 1;
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
173
  memset(&param, 0, sizeof(param));
520.1.22 by Brian Aker
Second pass of thd cleanup
174
  param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
1208.3.2 by brian
Update for Cursor renaming.
175
  param.ref_length= table->cursor->ref_length;
1 by brian
clean slate
176
  param.addon_field= 0;
177
  param.addon_length= 0;
1233.1.5 by Brian Aker
More table_flags converted.
178
  if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
1 by brian
clean slate
179
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
180
    /*
181
      Get the descriptors of all fields whose values are appended
1 by brian
clean slate
182
      to sorted fields and get its total length in param.spack_length.
183
    */
1578.2.16 by Brian Aker
Merge in change to getTable() to private the field objects.
184
    param.addon_field= get_addon_fields(session, table->getFields(),
1 by brian
clean slate
185
                                        param.sort_length,
186
                                        &param.addon_length);
187
  }
188
189
  table_sort.addon_buf= 0;
190
  table_sort.addon_length= param.addon_length;
191
  table_sort.addon_field= param.addon_field;
192
  table_sort.unpack= unpack_addon_fields;
193
  if (param.addon_field)
194
  {
195
    param.res_length= param.addon_length;
641.3.7 by Monty Taylor
More my_malloc removal.
196
    if (!(table_sort.addon_buf= (unsigned char *) malloc(param.addon_length)))
1 by brian
clean slate
197
      goto err;
198
  }
199
  else
200
  {
201
    param.res_length= param.ref_length;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
202
    /*
203
      The reference to the record is considered
1 by brian
clean slate
204
      as an additional sorted field
205
    */
206
    param.sort_length+= param.ref_length;
207
  }
208
  param.rec_length= param.sort_length+param.addon_length;
209
  param.max_rows= max_rows;
210
211
  if (select && select->quick)
212
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
213
    status_var_increment(session->status_var.filesort_range_count);
1 by brian
clean slate
214
  }
215
  else
216
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
217
    status_var_increment(session->status_var.filesort_scan_count);
1 by brian
clean slate
218
  }
219
#ifdef CAN_TRUST_RANGE
220
  if (select && select->quick && select->quick->records > 0L)
221
  {
1067.4.1 by Nathan Williams
First few changes at converting cmin to std::min.
222
    records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
1208.3.2 by brian
Update for Cursor renaming.
223
                 table->cursor->stats.records)+EXTRA_RECORDS;
1 by brian
clean slate
224
    selected_records_file=0;
225
  }
226
  else
227
#endif
228
  {
1208.3.2 by brian
Update for Cursor renaming.
229
    records= table->cursor->estimate_rows_upper_bound();
1 by brian
clean slate
230
    /*
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
231
      If number of records is not known, use as much of sort buffer
232
      as possible.
1 by brian
clean slate
233
    */
234
    if (records == HA_POS_ERROR)
235
      records--;  // we use 'records+1' below.
236
    selected_records_file= 0;
237
  }
238
239
  if (multi_byte_charset &&
641.3.7 by Monty Taylor
More my_malloc removal.
240
      !(param.tmp_buffer= (char*) malloc(param.sort_length)))
1 by brian
clean slate
241
    goto err;
242
520.1.22 by Brian Aker
Second pass of thd cleanup
243
  memavl= session->variables.sortbuff_size;
1067.4.7 by Nathan Williams
The remaining files using cmax have been converted to std::max.
244
  min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
1 by brian
clean slate
245
  while (memavl >= min_sort_memory)
246
  {
308 by Brian Aker
ulong conversion
247
    uint32_t old_memavl;
248
    uint32_t keys= memavl/(param.rec_length+sizeof(char*));
1067.4.1 by Nathan Williams
First few changes at converting cmin to std::min.
249
    param.keys= (uint32_t) min(records+1, (ha_rows)keys);
1 by brian
clean slate
250
    if ((table_sort.sort_keys=
481 by Brian Aker
Remove all of uchar.
251
	 (unsigned char **) make_char_array((char **) table_sort.sort_keys,
641.3.7 by Monty Taylor
More my_malloc removal.
252
                                            param.keys, param.rec_length)))
1 by brian
clean slate
253
      break;
1034.1.6 by Brian Aker
Increase the default sort buffer size.
254
    old_memavl= memavl;
255
    if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
1 by brian
clean slate
256
      memavl= min_sort_memory;
257
  }
258
  sort_keys= table_sort.sort_keys;
259
  if (memavl < min_sort_memory)
260
  {
261
    my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
262
    goto err;
263
  }
1556.1.1 by Brian Aker
Updates for moving temporary directory.
264
  if (open_cached_file(&buffpek_pointers,drizzle_tmpdir.c_str(),TEMP_PREFIX,
1 by brian
clean slate
265
		       DISK_BUFFER_SIZE, MYF(MY_WME)))
266
    goto err;
267
268
  param.keys--;  			/* TODO: check why we do this */
269
  param.sort_form= table;
270
  param.end=(param.local_sortorder=sortorder)+s_length;
1578.4.11 by Brian Aker
PAss through the code removing current_session
271
  if ((records=find_all_keys(session, &param,select,sort_keys, &buffpek_pointers,
1 by brian
clean slate
272
			     &tempfile, selected_records_file)) ==
273
      HA_POS_ERROR)
274
    goto err;
438.1.13 by Brian Aker
uint cleanup.
275
  maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
1 by brian
clean slate
276
277
  if (maxbuffer == 0)			// The whole set is in memory
278
  {
438.1.13 by Brian Aker
uint cleanup.
279
    if (save_index(&param,sort_keys,(uint32_t) records, &table_sort))
1 by brian
clean slate
280
      goto err;
281
  }
282
  else
283
  {
284
    if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
285
    {
460 by Monty Taylor
Removed x_free calls.
286
      if (table_sort.buffpek)
287
        free(table_sort.buffpek);
1 by brian
clean slate
288
      table_sort.buffpek= 0;
289
    }
290
    if (!(table_sort.buffpek=
481 by Brian Aker
Remove all of uchar.
291
          (unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
1 by brian
clean slate
292
                                 table_sort.buffpek)))
293
      goto err;
294
    buffpek= (BUFFPEK *) table_sort.buffpek;
295
    table_sort.buffpek_len= maxbuffer;
296
    close_cached_file(&buffpek_pointers);
297
	/* Open cached file if it isn't open */
298
    if (! my_b_inited(outfile) &&
1556.1.1 by Brian Aker
Updates for moving temporary directory.
299
	open_cached_file(outfile,drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER,
1 by brian
clean slate
300
			  MYF(MY_WME)))
301
      goto err;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
302
    if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
1 by brian
clean slate
303
      goto err;
304
305
    /*
306
      Use also the space previously used by string pointers in sort_buffer
307
      for temporary key storage.
308
    */
309
    param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
310
		param.rec_length-1);
311
    maxbuffer--;				// Offset from 0
481 by Brian Aker
Remove all of uchar.
312
    if (merge_many_buff(&param,(unsigned char*) sort_keys,buffpek,&maxbuffer,
1 by brian
clean slate
313
			&tempfile))
314
      goto err;
315
    if (flush_io_cache(&tempfile) ||
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
316
	reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
1 by brian
clean slate
317
      goto err;
481 by Brian Aker
Remove all of uchar.
318
    if (merge_index(&param,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
1 by brian
clean slate
319
		    outfile))
320
      goto err;
321
  }
322
  if (records > param.max_rows)
323
    records=param.max_rows;
324
  error =0;
325
326
 err:
327
  if (param.tmp_buffer)
460 by Monty Taylor
Removed x_free calls.
328
    if (param.tmp_buffer)
329
      free(param.tmp_buffer);
1 by brian
clean slate
330
  if (!subselect || !subselect->is_uncacheable())
331
  {
1510.3.3 by mordred
Fixed note from cppcheck - passing NULL to free is valid, so the check for non-null here is redundant. Also, casting to unsigned char * is pretty pointless.
332
    free(sort_keys);
1 by brian
clean slate
333
    table_sort.sort_keys= 0;
1510.3.3 by mordred
Fixed note from cppcheck - passing NULL to free is valid, so the check for non-null here is redundant. Also, casting to unsigned char * is pretty pointless.
334
    free(buffpek);
1 by brian
clean slate
335
    table_sort.buffpek= 0;
336
    table_sort.buffpek_len= 0;
337
  }
338
  close_cached_file(&tempfile);
339
  close_cached_file(&buffpek_pointers);
340
  if (my_b_inited(outfile))
341
  {
342
    if (flush_io_cache(outfile))
343
      error=1;
344
    {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
345
      internal::my_off_t save_pos=outfile->pos_in_file;
1 by brian
clean slate
346
      /* For following reads */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
347
      if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
1 by brian
clean slate
348
	error=1;
349
      outfile->end_of_file=save_pos;
350
    }
351
  }
352
  if (error)
353
    my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
354
               MYF(ME_ERROR+ME_WAITTANG));
355
  else
520.1.22 by Brian Aker
Second pass of thd cleanup
356
    statistic_add(session->status_var.filesort_rows,
308 by Brian Aker
ulong conversion
357
		  (uint32_t) records, &LOCK_status);
1 by brian
clean slate
358
  *examined_rows= param.examined_rows;
327.2.3 by Brian Aker
Refactoring of class Table
359
  memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
1126.10.9 by Padraig O'Sullivan
Added calls to the filesort dtrace probes.
360
  DRIZZLE_FILESORT_DONE(error, records);
361
  return (error ? HA_POS_ERROR : records);
1 by brian
clean slate
362
} /* filesort */
363
364
1109.1.4 by Brian Aker
More Table refactor
365
void Table::filesort_free_buffers(bool full)
1 by brian
clean slate
366
{
1109.1.4 by Brian Aker
More Table refactor
367
  if (sort.record_pointers)
1 by brian
clean slate
368
  {
1109.1.4 by Brian Aker
More Table refactor
369
    free((unsigned char*) sort.record_pointers);
370
    sort.record_pointers=0;
1 by brian
clean slate
371
  }
372
  if (full)
373
  {
1109.1.4 by Brian Aker
More Table refactor
374
    if (sort.sort_keys )
1 by brian
clean slate
375
    {
1109.1.4 by Brian Aker
More Table refactor
376
      if ((unsigned char*) sort.sort_keys)
377
        free((unsigned char*) sort.sort_keys);
378
      sort.sort_keys= 0;
1 by brian
clean slate
379
    }
1109.1.4 by Brian Aker
More Table refactor
380
    if (sort.buffpek)
1 by brian
clean slate
381
    {
1109.1.4 by Brian Aker
More Table refactor
382
      if ((unsigned char*) sort.buffpek)
383
        free((unsigned char*) sort.buffpek);
384
      sort.buffpek= 0;
385
      sort.buffpek_len= 0;
1 by brian
clean slate
386
    }
387
  }
1109.1.4 by Brian Aker
More Table refactor
388
  if (sort.addon_buf)
1 by brian
clean slate
389
  {
1109.1.4 by Brian Aker
More Table refactor
390
    free((char *) sort.addon_buf);
391
    free((char *) sort.addon_field);
392
    sort.addon_buf=0;
393
    sort.addon_field=0;
1 by brian
clean slate
394
  }
395
}
396
397
/** Make a array of string pointers. */
398
438.1.13 by Brian Aker
uint cleanup.
399
static char **make_char_array(char **old_pos, register uint32_t fields,
641.3.7 by Monty Taylor
More my_malloc removal.
400
                              uint32_t length)
1 by brian
clean slate
401
{
402
  register char **pos;
403
  char *char_pos;
404
405
  if (old_pos ||
641.3.9 by Monty Taylor
More removal of my_malloc.
406
      (old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
1 by brian
clean slate
407
  {
408
    pos=old_pos; char_pos=((char*) (pos+fields)) -length;
409
    while (fields--) *(pos++) = (char_pos+= length);
410
  }
411
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
412
  return(old_pos);
1 by brian
clean slate
413
} /* make_char_array */
414
415
416
/** Read 'count' number of buffer pointers into memory. */
417
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
418
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
481 by Brian Aker
Remove all of uchar.
419
                                     unsigned char *buf)
1 by brian
clean slate
420
{
308 by Brian Aker
ulong conversion
421
  uint32_t length= sizeof(BUFFPEK)*count;
481 by Brian Aker
Remove all of uchar.
422
  unsigned char *tmp= buf;
1 by brian
clean slate
423
  if (count > UINT_MAX/sizeof(BUFFPEK))
424
    return 0; /* sizeof(BUFFPEK)*count will overflow */
425
  if (!tmp)
641.3.7 by Monty Taylor
More my_malloc removal.
426
    tmp= (unsigned char *)malloc(length);
1 by brian
clean slate
427
  if (tmp)
428
  {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
429
    if (reinit_io_cache(buffpek_pointers,internal::READ_CACHE,0L,0,0) ||
481 by Brian Aker
Remove all of uchar.
430
	my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
1 by brian
clean slate
431
    {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
432
      free((char*) tmp);
1 by brian
clean slate
433
      tmp=0;
434
    }
435
  }
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
436
  return(tmp);
1 by brian
clean slate
437
}
438
439
440
/**
441
  Search after sort_keys and write them into tempfile.
442
  All produced sequences are guaranteed to be non-empty.
443
444
  @param param             Sorting parameter
445
  @param select            Use this to get source data
446
  @param sort_keys         Array of pointers to sort key + addon buffers.
447
  @param buffpek_pointers  File to write BUFFPEKs describing sorted segments
448
                           in tempfile.
449
  @param tempfile          File to write sorted sequences of sortkeys to.
450
  @param indexfile         If !NULL, use it for source data (contains rowids)
451
452
  @note
453
    Basic idea:
454
    @verbatim
455
     while (get_next_sortkey())
456
     {
457
       if (no free space in sort_keys buffers)
458
       {
459
         sort sort_keys buffer;
460
         dump sorted sequence to 'tempfile';
461
         dump BUFFPEK describing sequence location into 'buffpek_pointers';
462
       }
463
       put sort key into 'sort_keys';
464
     }
465
     if (sort_keys has some elements && dumped at least once)
466
       sort-dump-dump as above;
467
     else
468
       don't sort, leave sort_keys array to be sorted by caller.
469
  @endverbatim
470
471
  @retval
472
    Number of records written on success.
473
  @retval
474
    HA_POS_ERROR on error.
475
*/
476
1578.4.11 by Brian Aker
PAss through the code removing current_session
477
static ha_rows find_all_keys(Session *session,
478
                             SORTPARAM *param, 
1237.13.3 by Padraig O'Sullivan
Performed numerous style cleanups in range.[cc,h].
479
                             optimizer::SqlSelect *select,
481 by Brian Aker
Remove all of uchar.
480
			     unsigned char **sort_keys,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
481
			     internal::IO_CACHE *buffpek_pointers,
482
			     internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
1 by brian
clean slate
483
{
484
  int error,flag,quick_select;
438.1.13 by Brian Aker
uint cleanup.
485
  uint32_t idx,indexpos,ref_length;
481 by Brian Aker
Remove all of uchar.
486
  unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
487
  internal::my_off_t record;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
488
  Table *sort_form;
520.1.22 by Brian Aker
Second pass of thd cleanup
489
  volatile Session::killed_state *killed= &session->killed;
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
490
  Cursor *file;
1103.6.2 by Padraig O'Sullivan
Removing references to MY_BITMAP throughout the code base and updating calls
491
  MyBitmap *save_read_set, *save_write_set;
1 by brian
clean slate
492
493
  idx=indexpos=0;
494
  error=quick_select=0;
495
  sort_form=param->sort_form;
1208.3.2 by brian
Update for Cursor renaming.
496
  file= sort_form->cursor;
1 by brian
clean slate
497
  ref_length=param->ref_length;
498
  ref_pos= ref_buff;
499
  quick_select=select && select->quick;
500
  record=0;
1220.2.1 by Brian Aker
Move cursor flags up to storage engine flags. These need to be merged.
501
  flag= ((!indexfile && ! file->isOrdered())
1 by brian
clean slate
502
	 || quick_select);
503
  if (indexfile || flag)
504
    ref_pos= &file->ref[0];
505
  next_pos=ref_pos;
506
  if (! indexfile && ! quick_select)
507
  {
481 by Brian Aker
Remove all of uchar.
508
    next_pos=(unsigned char*) 0;			/* Find records in sequence */
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
509
    file->startTableScan(1);
1 by brian
clean slate
510
    file->extra_opt(HA_EXTRA_CACHE,
1578.4.11 by Brian Aker
PAss through the code removing current_session
511
		    session->variables.read_buff_size);
1 by brian
clean slate
512
  }
513
1538 by Brian Aker
Code shuffle on ReadRecord
514
  ReadRecord read_record_info;
1 by brian
clean slate
515
  if (quick_select)
516
  {
517
    if (select->quick->reset())
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
518
      return(HA_POS_ERROR);
1538 by Brian Aker
Code shuffle on ReadRecord
519
1578.4.11 by Brian Aker
PAss through the code removing current_session
520
    read_record_info.init_read_record(session, select->quick->head, select, 1, 1);
1 by brian
clean slate
521
  }
522
523
  /* Remember original bitmaps */
524
  save_read_set=  sort_form->read_set;
525
  save_write_set= sort_form->write_set;
526
  /* Set up temporary column read map for columns used by sort */
1103.6.3 by Padraig O'Sullivan
Fixing up more calls to the old bitmap API.
527
  sort_form->tmp_set.clearAll();
1 by brian
clean slate
528
  /* Temporary set for register_used_fields and register_field_in_read_map */
529
  sort_form->read_set= &sort_form->tmp_set;
530
  register_used_fields(param);
531
  if (select && select->cond)
532
    select->cond->walk(&Item::register_field_in_read_map, 1,
481 by Brian Aker
Remove all of uchar.
533
                       (unsigned char*) sort_form);
1 by brian
clean slate
534
  sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
535
536
  for (;;)
537
  {
538
    if (quick_select)
539
    {
540
      if ((error= read_record_info.read_record(&read_record_info)))
541
      {
542
        error= HA_ERR_END_OF_FILE;
543
        break;
544
      }
545
      file->position(sort_form->record[0]);
546
    }
547
    else					/* Not quick-select */
548
    {
549
      if (indexfile)
550
      {
971.6.11 by Eric Day
Removed purecov messages.
551
	if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length))
1 by brian
clean slate
552
	{
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
553
	  error= errno ? errno : -1;		/* Abort */
1 by brian
clean slate
554
	  break;
555
	}
556
	error=file->rnd_pos(sort_form->record[0],next_pos);
557
      }
558
      else
559
      {
560
	error=file->rnd_next(sort_form->record[0]);
383.7.1 by Andrey Zhakov
Initial submit of code and tests
561
1 by brian
clean slate
562
	if (!flag)
563
	{
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
564
	  internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
1532.1.15 by Brian Aker
Partial encapsulation of TableShare from Table.
565
	  record+= sort_form->getShare()->db_record_offset;
1 by brian
clean slate
566
	}
567
	else if (!error)
568
	  file->position(sort_form->record[0]);
569
      }
570
      if (error && error != HA_ERR_RECORD_DELETED)
571
	break;
572
    }
573
574
    if (*killed)
575
    {
576
      if (!indexfile && !quick_select)
577
      {
578
        (void) file->extra(HA_EXTRA_NO_CACHE);
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
579
        file->endTableScan();
1 by brian
clean slate
580
      }
971.6.11 by Eric Day
Removed purecov messages.
581
      return(HA_POS_ERROR);
1 by brian
clean slate
582
    }
583
    if (error == 0)
584
      param->examined_rows++;
585
    if (error == 0 && (!select || select->skip_record() == 0))
586
    {
587
      if (idx == param->keys)
588
      {
589
	if (write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
590
	  return(HA_POS_ERROR);
1 by brian
clean slate
591
	idx=0;
592
	indexpos++;
593
      }
594
      make_sortkey(param,sort_keys[idx++],ref_pos);
595
    }
596
    else
597
      file->unlock_row();
598
    /* It does not make sense to read more keys in case of a fatal error */
520.1.22 by Brian Aker
Second pass of thd cleanup
599
    if (session->is_error())
1 by brian
clean slate
600
      break;
601
  }
602
  if (quick_select)
603
  {
604
    /*
605
      index_merge quick select uses table->sort when retrieving rows, so free
606
      resoures it has allocated.
607
    */
1538 by Brian Aker
Code shuffle on ReadRecord
608
    read_record_info.end_read_record();
1 by brian
clean slate
609
  }
610
  else
611
  {
612
    (void) file->extra(HA_EXTRA_NO_CACHE);	/* End cacheing of records */
613
    if (!next_pos)
1491.1.10 by Jay Pipes
ha_rnd_init -> startTableScan, rnd_init -> doStartTableScan, ha_rnd_end -> endTableScan, rnd_end -> doEndTableScan
614
      file->endTableScan();
1 by brian
clean slate
615
  }
616
520.1.22 by Brian Aker
Second pass of thd cleanup
617
  if (session->is_error())
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
618
    return(HA_POS_ERROR);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
619
1 by brian
clean slate
620
  /* Signal we should use orignal column read and write maps */
621
  sort_form->column_bitmaps_set(save_read_set, save_write_set);
622
623
  if (error != HA_ERR_END_OF_FILE)
624
  {
1216.1.1 by Brian Aker
Move print_error up to Engine.
625
    sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
971.6.11 by Eric Day
Removed purecov messages.
626
    return(HA_POS_ERROR);
1 by brian
clean slate
627
  }
628
  if (indexpos && idx &&
629
      write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
971.6.11 by Eric Day
Removed purecov messages.
630
    return(HA_POS_ERROR);
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
631
  return(my_b_inited(tempfile) ?
1 by brian
clean slate
632
	      (ha_rows) (my_b_tell(tempfile)/param->rec_length) :
633
	      idx);
634
} /* find_all_keys */
635
636
637
/**
638
  @details
639
  Sort the buffer and write:
640
  -# the sorted sequence to tempfile
641
  -# a BUFFPEK describing the sorted sequence position to buffpek_pointers
642
643
    (was: Skriver en buffert med nycklar till filen)
644
645
  @param param             Sort parameters
646
  @param sort_keys         Array of pointers to keys to sort
647
  @param count             Number of elements in sort_keys array
648
  @param buffpek_pointers  One 'BUFFPEK' struct will be written into this file.
649
                           The BUFFPEK::{file_pos, count} will indicate where
650
                           the sorted data was stored.
651
  @param tempfile          The sorted sequence will be written into this file.
652
653
  @retval
654
    0 OK
655
  @retval
656
    1 Error
657
*/
658
659
static int
481 by Brian Aker
Remove all of uchar.
660
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
661
           internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
1 by brian
clean slate
662
{
663
  size_t sort_length, rec_length;
481 by Brian Aker
Remove all of uchar.
664
  unsigned char **end;
1 by brian
clean slate
665
  BUFFPEK buffpek;
666
667
  sort_length= param->sort_length;
668
  rec_length= param->rec_length;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
669
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1 by brian
clean slate
670
  if (!my_b_inited(tempfile) &&
1556.1.1 by Brian Aker
Updates for moving temporary directory.
671
      open_cached_file(tempfile, drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE,
1 by brian
clean slate
672
                       MYF(MY_WME)))
971.6.11 by Eric Day
Removed purecov messages.
673
    goto err;
1 by brian
clean slate
674
  /* check we won't have more buffpeks than we can possibly keep in memory */
151 by Brian Aker
Ulonglong to uint64_t
675
  if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
1 by brian
clean slate
676
    goto err;
677
  buffpek.file_pos= my_b_tell(tempfile);
678
  if ((ha_rows) count > param->max_rows)
971.6.11 by Eric Day
Removed purecov messages.
679
    count=(uint32_t) param->max_rows;
1 by brian
clean slate
680
  buffpek.count=(ha_rows) count;
681
  for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
481 by Brian Aker
Remove all of uchar.
682
    if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
1 by brian
clean slate
683
      goto err;
481 by Brian Aker
Remove all of uchar.
684
  if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
1 by brian
clean slate
685
    goto err;
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
686
  return(0);
1 by brian
clean slate
687
688
err:
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
689
  return(1);
1 by brian
clean slate
690
} /* write_keys */
691
692
693
/**
694
  Store length as suffix in high-byte-first order.
695
*/
696
481 by Brian Aker
Remove all of uchar.
697
static inline void store_length(unsigned char *to, uint32_t length, uint32_t pack_length)
1 by brian
clean slate
698
{
699
  switch (pack_length) {
700
  case 1:
481 by Brian Aker
Remove all of uchar.
701
    *to= (unsigned char) length;
1 by brian
clean slate
702
    break;
703
  case 2:
704
    mi_int2store(to, length);
705
    break;
706
  case 3:
707
    mi_int3store(to, length);
708
    break;
709
  default:
710
    mi_int4store(to, length);
711
    break;
712
  }
713
}
714
715
716
/** Make a sort-key from record. */
717
718
static void make_sortkey(register SORTPARAM *param,
481 by Brian Aker
Remove all of uchar.
719
			 register unsigned char *to, unsigned char *ref_pos)
1 by brian
clean slate
720
{
721
  register Field *field;
722
  register SORT_FIELD *sort_field;
937.2.7 by Stewart Smith
typesafe set_if_smaller/set_if_greater fixes from Solaris
723
  size_t length;
1 by brian
clean slate
724
725
  for (sort_field=param->local_sortorder ;
726
       sort_field != param->end ;
727
       sort_field++)
728
  {
729
    bool maybe_null=0;
730
    if ((field=sort_field->field))
731
    {						// Field
732
      if (field->maybe_null())
733
      {
734
	if (field->is_null())
735
	{
736
	  if (sort_field->reverse)
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
737
	    memset(to, 255, sort_field->length+1);
1 by brian
clean slate
738
	  else
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
739
	    memset(to, 0, sort_field->length+1);
1 by brian
clean slate
740
	  to+= sort_field->length+1;
741
	  continue;
742
	}
743
	else
744
	  *to++=1;
745
      }
746
      field->sort_string(to, sort_field->length);
747
    }
748
    else
749
    {						// Item
750
      Item *item=sort_field->item;
751
      maybe_null= item->maybe_null;
752
      switch (sort_field->result_type) {
753
      case STRING_RESULT:
754
      {
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
755
        const CHARSET_INFO * const cs=item->collation.collation;
1 by brian
clean slate
756
        char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
757
        int diff;
438.1.13 by Brian Aker
uint cleanup.
758
        uint32_t sort_field_length;
1 by brian
clean slate
759
760
        if (maybe_null)
761
          *to++=1;
762
        /* All item->str() to use some extra byte for end null.. */
763
        String tmp((char*) to,sort_field->length+4,cs);
764
        String *res= item->str_result(&tmp);
765
        if (!res)
766
        {
767
          if (maybe_null)
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
768
            memset(to-1, 0, sort_field->length+1);
1 by brian
clean slate
769
          else
770
          {
771
            /*
772
              This should only happen during extreme conditions if we run out
773
              of memory or have an item marked not null when it can be null.
774
              This code is here mainly to avoid a hard crash in this case.
775
            */
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
776
            assert(0);
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
777
            memset(to, 0, sort_field->length);	// Avoid crash
1 by brian
clean slate
778
          }
779
          break;
780
        }
781
        length= res->length();
782
        sort_field_length= sort_field->length - sort_field->suffix_length;
783
        diff=(int) (sort_field_length - length);
784
        if (diff < 0)
785
        {
786
          diff=0;
787
          length= sort_field_length;
788
        }
789
        if (sort_field->suffix_length)
790
        {
791
          /* Store length last in result_string */
792
          store_length(to + sort_field_length, length,
793
                       sort_field->suffix_length);
794
        }
795
        if (sort_field->need_strxnfrm)
796
        {
797
          char *from=(char*) res->ptr();
438.1.13 by Brian Aker
uint cleanup.
798
          uint32_t tmp_length;
481 by Brian Aker
Remove all of uchar.
799
          if ((unsigned char*) from == to)
1 by brian
clean slate
800
          {
801
            set_if_smaller(length,sort_field->length);
802
            memcpy(param->tmp_buffer,from,length);
803
            from=param->tmp_buffer;
804
          }
805
          tmp_length= my_strnxfrm(cs,to,sort_field->length,
481 by Brian Aker
Remove all of uchar.
806
                                  (unsigned char*) from, length);
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
807
          assert(tmp_length == sort_field->length);
1 by brian
clean slate
808
        }
809
        else
810
        {
481 by Brian Aker
Remove all of uchar.
811
          my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
1 by brian
clean slate
812
          cs->cset->fill(cs, (char *)to+length,diff,fill_char);
813
        }
814
        break;
815
      }
816
      case INT_RESULT:
817
	{
152 by Brian Aker
longlong replacement
818
          int64_t value= item->val_int_result();
1 by brian
clean slate
819
          if (maybe_null)
820
          {
971.6.11 by Eric Day
Removed purecov messages.
821
	    *to++=1;
1 by brian
clean slate
822
            if (item->null_value)
823
            {
824
              if (maybe_null)
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
825
                memset(to-1, 0, sort_field->length+1);
1 by brian
clean slate
826
              else
827
              {
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
828
                memset(to, 0, sort_field->length);
1 by brian
clean slate
829
              }
830
              break;
831
            }
832
          }
481 by Brian Aker
Remove all of uchar.
833
	  to[7]= (unsigned char) value;
834
	  to[6]= (unsigned char) (value >> 8);
835
	  to[5]= (unsigned char) (value >> 16);
836
	  to[4]= (unsigned char) (value >> 24);
837
	  to[3]= (unsigned char) (value >> 32);
838
	  to[2]= (unsigned char) (value >> 40);
839
	  to[1]= (unsigned char) (value >> 48);
1 by brian
clean slate
840
          if (item->unsigned_flag)                    /* Fix sign */
481 by Brian Aker
Remove all of uchar.
841
            to[0]= (unsigned char) (value >> 56);
1 by brian
clean slate
842
          else
481 by Brian Aker
Remove all of uchar.
843
            to[0]= (unsigned char) (value >> 56) ^ 128;	/* Reverse signbit */
1 by brian
clean slate
844
	  break;
845
	}
846
      case DECIMAL_RESULT:
847
        {
848
          my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
849
          if (maybe_null)
850
          {
851
            if (item->null_value)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
852
            {
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
853
              memset(to, 0, sort_field->length+1);
1 by brian
clean slate
854
              to++;
855
              break;
856
            }
857
            *to++=1;
858
          }
859
          my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to,
860
                            item->max_length - (item->decimals ? 1:0),
861
                            item->decimals);
862
         break;
863
        }
864
      case REAL_RESULT:
865
	{
866
          double value= item->val_result();
867
	  if (maybe_null)
868
          {
869
            if (item->null_value)
870
            {
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
871
              memset(to, 0, sort_field->length+1);
1 by brian
clean slate
872
              to++;
873
              break;
874
            }
875
	    *to++=1;
876
          }
481 by Brian Aker
Remove all of uchar.
877
	  change_double_for_sort(value,(unsigned char*) to);
1 by brian
clean slate
878
	  break;
879
	}
880
      case ROW_RESULT:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
881
      default:
1 by brian
clean slate
882
	// This case should never be choosen
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
883
	assert(0);
1 by brian
clean slate
884
	break;
885
      }
886
    }
887
    if (sort_field->reverse)
888
    {							/* Revers key */
889
      if (maybe_null)
890
        to[-1]= ~to[-1];
891
      length=sort_field->length;
892
      while (length--)
893
      {
481 by Brian Aker
Remove all of uchar.
894
	*to = (unsigned char) (~ *to);
1 by brian
clean slate
895
	to++;
896
      }
897
    }
898
    else
899
      to+= sort_field->length;
900
  }
901
902
  if (param->addon_field)
903
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
904
    /*
1 by brian
clean slate
905
      Save field values appended to sorted fields.
906
      First null bit indicators are appended then field values follow.
907
      In this implementation we use fixed layout for field values -
908
      the same for all records.
909
    */
910
    SORT_ADDON_FIELD *addonf= param->addon_field;
481 by Brian Aker
Remove all of uchar.
911
    unsigned char *nulls= to;
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
912
    assert(addonf != 0);
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
913
    memset(nulls, 0, addonf->offset);
1 by brian
clean slate
914
    to+= addonf->offset;
915
    for ( ; (field= addonf->field) ; addonf++)
916
    {
917
      if (addonf->null_bit && field->is_null())
918
      {
919
        nulls[addonf->null_offset]|= addonf->null_bit;
920
#ifdef HAVE_purify
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
921
	memset(to, 0, addonf->length);
1 by brian
clean slate
922
#endif
923
      }
924
      else
925
      {
926
#ifdef HAVE_purify
481 by Brian Aker
Remove all of uchar.
927
        unsigned char *end= field->pack(to, field->ptr);
438.1.13 by Brian Aker
uint cleanup.
928
	uint32_t length= (uint32_t) ((to + addonf->length) - end);
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
929
	assert((int) length >= 0);
1 by brian
clean slate
930
	if (length)
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
931
	  memset(end, 0, length);
1 by brian
clean slate
932
#else
933
        (void) field->pack(to, field->ptr);
934
#endif
935
      }
936
      to+= addonf->length;
937
    }
938
  }
939
  else
940
  {
941
    /* Save filepos last */
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
942
    memcpy(to, ref_pos, (size_t) param->ref_length);
1 by brian
clean slate
943
  }
944
  return;
945
}
946
947
948
/*
949
  Register fields used by sorting in the sorted table's read set
950
*/
951
952
static void register_used_fields(SORTPARAM *param)
953
{
954
  register SORT_FIELD *sort_field;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
955
  Table *table=param->sort_form;
1 by brian
clean slate
956
957
  for (sort_field= param->local_sortorder ;
958
       sort_field != param->end ;
959
       sort_field++)
960
  {
961
    Field *field;
962
    if ((field= sort_field->field))
963
    {
964
      if (field->table == table)
1005.2.12 by Monty Taylor
Moved some things to the API.
965
        table->setReadSet(field->field_index);
1 by brian
clean slate
966
    }
967
    else
968
    {						// Item
969
      sort_field->item->walk(&Item::register_field_in_read_map, 1,
481 by Brian Aker
Remove all of uchar.
970
                             (unsigned char *) table);
1 by brian
clean slate
971
    }
972
  }
973
974
  if (param->addon_field)
975
  {
976
    SORT_ADDON_FIELD *addonf= param->addon_field;
977
    Field *field;
978
    for ( ; (field= addonf->field) ; addonf++)
1005.2.12 by Monty Taylor
Moved some things to the API.
979
      table->setReadSet(field->field_index);
1 by brian
clean slate
980
  }
981
  else
982
  {
983
    /* Save filepos last */
984
    table->prepare_for_position();
985
  }
986
}
987
988
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
989
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
327.2.3 by Brian Aker
Refactoring of class Table
990
                       filesort_info_st *table_sort)
1 by brian
clean slate
991
{
438.1.13 by Brian Aker
uint cleanup.
992
  uint32_t offset,res_length;
481 by Brian Aker
Remove all of uchar.
993
  unsigned char *to;
1 by brian
clean slate
994
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
995
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
1 by brian
clean slate
996
  res_length= param->res_length;
997
  offset= param->rec_length-res_length;
998
  if ((ha_rows) count > param->max_rows)
438.1.13 by Brian Aker
uint cleanup.
999
    count=(uint32_t) param->max_rows;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1000
  if (!(to= table_sort->record_pointers=
641.3.7 by Monty Taylor
More my_malloc removal.
1001
        (unsigned char*) malloc(res_length*count)))
971.6.11 by Eric Day
Removed purecov messages.
1002
    return(1);
481 by Brian Aker
Remove all of uchar.
1003
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1 by brian
clean slate
1004
  {
1005
    memcpy(to, *sort_keys+offset, res_length);
1006
    to+= res_length;
1007
  }
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1008
  return(0);
1 by brian
clean slate
1009
}
1010
1011
1012
/** Merge buffers to make < MERGEBUFF2 buffers. */
1013
481 by Brian Aker
Remove all of uchar.
1014
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1015
		    BUFFPEK *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1 by brian
clean slate
1016
{
438.1.13 by Brian Aker
uint cleanup.
1017
  register uint32_t i;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1018
  internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1 by brian
clean slate
1019
  BUFFPEK *lastbuff;
1020
1021
  if (*maxbuffer < MERGEBUFF2)
971.6.11 by Eric Day
Removed purecov messages.
1022
    return(0);
1 by brian
clean slate
1023
  if (flush_io_cache(t_file) ||
1556.1.1 by Brian Aker
Updates for moving temporary directory.
1024
      open_cached_file(&t_file2,drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE,
1 by brian
clean slate
1025
			MYF(MY_WME)))
971.6.11 by Eric Day
Removed purecov messages.
1026
    return(1);
1 by brian
clean slate
1027
1028
  from_file= t_file ; to_file= &t_file2;
1029
  while (*maxbuffer >= MERGEBUFF2)
1030
  {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1031
    if (reinit_io_cache(from_file,internal::READ_CACHE,0L,0,0))
1 by brian
clean slate
1032
      goto cleanup;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1033
    if (reinit_io_cache(to_file,internal::WRITE_CACHE,0L,0,0))
1 by brian
clean slate
1034
      goto cleanup;
1035
    lastbuff=buffpek;
1036
    for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1037
    {
1038
      if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1039
			buffpek+i,buffpek+i+MERGEBUFF-1,0))
1040
      goto cleanup;
1041
    }
1042
    if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1043
		      buffpek+i,buffpek+ *maxbuffer,0))
971.6.11 by Eric Day
Removed purecov messages.
1044
      break;
1 by brian
clean slate
1045
    if (flush_io_cache(to_file))
971.6.11 by Eric Day
Removed purecov messages.
1046
      break;
1 by brian
clean slate
1047
    temp=from_file; from_file=to_file; to_file=temp;
1048
    setup_io_cache(from_file);
1049
    setup_io_cache(to_file);
438.1.13 by Brian Aker
uint cleanup.
1050
    *maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1 by brian
clean slate
1051
  }
1052
cleanup:
1053
  close_cached_file(to_file);			// This holds old result
1054
  if (to_file == t_file)
1055
  {
1056
    *t_file=t_file2;				// Copy result file
1057
    setup_io_cache(t_file);
1058
  }
1059
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1060
  return(*maxbuffer >= MERGEBUFF2);	/* Return 1 if interrupted */
1 by brian
clean slate
1061
} /* merge_many_buff */
1062
1063
1064
/**
1065
  Read data to buffer.
1066
1067
  @retval
438.1.13 by Brian Aker
uint cleanup.
1068
    (uint32_t)-1 if something goes wrong
1 by brian
clean slate
1069
*/
1070
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1071
uint32_t read_to_buffer(internal::IO_CACHE *fromfile, BUFFPEK *buffpek,
1067.4.1 by Nathan Williams
First few changes at converting cmin to std::min.
1072
                        uint32_t rec_length)
1 by brian
clean slate
1073
{
438.1.13 by Brian Aker
uint cleanup.
1074
  register uint32_t count;
1075
  uint32_t length;
1 by brian
clean slate
1076
1067.4.1 by Nathan Williams
First few changes at converting cmin to std::min.
1077
  if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1 by brian
clean slate
1078
  {
481 by Brian Aker
Remove all of uchar.
1079
    if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
971.6.11 by Eric Day
Removed purecov messages.
1080
      return((uint32_t) -1);
1067.4.1 by Nathan Williams
First few changes at converting cmin to std::min.
1081
1082
    buffpek->key= buffpek->base;
1 by brian
clean slate
1083
    buffpek->file_pos+= length;			/* New filepos */
1067.4.1 by Nathan Williams
First few changes at converting cmin to std::min.
1084
    buffpek->count-= count;
1 by brian
clean slate
1085
    buffpek->mem_count= count;
1086
  }
1087
  return (count*rec_length);
1088
} /* read_to_buffer */
1089
1090
897.1.11 by Padraig
Giving function object a better name for this scenario.
1091
class compare_functor
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1092
{
897.1.6 by Padraig
Cleaning up merge_buffers() function a little bit.
1093
  qsort2_cmp key_compare;
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1094
  void *key_compare_arg;
1095
  public:
897.1.11 by Padraig
Giving function object a better name for this scenario.
1096
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
897.1.6 by Padraig
Cleaning up merge_buffers() function a little bit.
1097
    : key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
897.1.16 by Padraig O'Sullivan
Cleaning up my function object. Making it const correct and putting
1098
  inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1099
  {
897.1.16 by Padraig O'Sullivan
Cleaning up my function object. Making it const correct and putting
1100
    int val= key_compare(key_compare_arg,
1101
                      &i->key, &j->key);
897.1.18 by Padraig O'Sullivan
Cleaning up my function object a little bit.
1102
    return (val >= 0);
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1103
  }
1104
};
1105
1 by brian
clean slate
1106
1107
/**
1108
  Merge buffers to one buffer.
1109
1110
  @param param        Sort parameter
1111
  @param from_file    File with source data (BUFFPEKs point to this file)
1112
  @param to_file      File to write the sorted result data.
1113
  @param sort_buffer  Buffer for data to store up to MERGEBUFF2 sort keys.
1114
  @param lastbuff     OUT Store here BUFFPEK describing data written to to_file
1115
  @param Fb           First element in source BUFFPEKs array
1116
  @param Tb           Last element in source BUFFPEKs array
1117
  @param flag
1118
1119
  @retval
1120
    0      OK
1121
  @retval
1122
    other  error
1123
*/
1124
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1125
int merge_buffers(SORTPARAM *param, internal::IO_CACHE *from_file,
1126
                  internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1 by brian
clean slate
1127
                  BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1128
                  int flag)
1129
{
1130
  int error;
438.1.13 by Brian Aker
uint cleanup.
1131
  uint32_t rec_length,res_length,offset;
1 by brian
clean slate
1132
  size_t sort_length;
308 by Brian Aker
ulong conversion
1133
  uint32_t maxcount;
1 by brian
clean slate
1134
  ha_rows max_rows,org_max_rows;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1135
  internal::my_off_t to_start_filepos;
481 by Brian Aker
Remove all of uchar.
1136
  unsigned char *strpos;
1 by brian
clean slate
1137
  BUFFPEK *buffpek;
1138
  qsort2_cmp cmp;
1139
  void *first_cmp_arg;
520.1.22 by Brian Aker
Second pass of thd cleanup
1140
  volatile Session::killed_state *killed= &current_session->killed;
520.1.21 by Brian Aker
THD -> Session rename
1141
  Session::killed_state not_killable;
1 by brian
clean slate
1142
520.1.22 by Brian Aker
Second pass of thd cleanup
1143
  status_var_increment(current_session->status_var.filesort_merge_passes);
1 by brian
clean slate
1144
  if (param->not_killable)
1145
  {
1146
    killed= &not_killable;
520.1.21 by Brian Aker
THD -> Session rename
1147
    not_killable= Session::NOT_KILLED;
1 by brian
clean slate
1148
  }
1149
1150
  error=0;
1151
  rec_length= param->rec_length;
1152
  res_length= param->res_length;
1153
  sort_length= param->sort_length;
1154
  offset= rec_length-res_length;
438.1.13 by Brian Aker
uint cleanup.
1155
  maxcount= (uint32_t) (param->keys/((uint32_t) (Tb-Fb) +1));
1 by brian
clean slate
1156
  to_start_filepos= my_b_tell(to_file);
481 by Brian Aker
Remove all of uchar.
1157
  strpos= (unsigned char*) sort_buffer;
1 by brian
clean slate
1158
  org_max_rows=max_rows= param->max_rows;
1159
1160
  /* The following will fire if there is not enough space in sort_buffer */
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1161
  assert(maxcount!=0);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1162
1 by brian
clean slate
1163
  if (param->unique_buff)
1164
  {
1165
    cmp= param->compare;
1166
    first_cmp_arg= (void *) &param->cmp_context;
1167
  }
1168
  else
1169
  {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1170
    cmp= internal::get_ptr_compare(sort_length);
1 by brian
clean slate
1171
    first_cmp_arg= (void*) &sort_length;
1172
  }
897.1.11 by Padraig
Giving function object a better name for this scenario.
1173
  priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor > 
1174
    queue(compare_functor(cmp, first_cmp_arg));
1 by brian
clean slate
1175
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1176
  {
1177
    buffpek->base= strpos;
1178
    buffpek->max_keys= maxcount;
438.1.13 by Brian Aker
uint cleanup.
1179
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1 by brian
clean slate
1180
                                                                         rec_length));
1181
    if (error == -1)
971.6.11 by Eric Day
Removed purecov messages.
1182
      goto err;
1 by brian
clean slate
1183
    buffpek->max_keys= buffpek->mem_count;	// If less data in buffers than expected
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1184
    queue.push(buffpek);
1 by brian
clean slate
1185
  }
1186
1187
  if (param->unique_buff)
1188
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1189
    /*
1 by brian
clean slate
1190
       Called by Unique::get()
1191
       Copy the first argument to param->unique_buff for unique removal.
1192
       Store it also in 'to_file'.
1193
1194
       This is safe as we know that there is always more than one element
1195
       in each block to merge (This is guaranteed by the Unique:: algorithm
1196
    */
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1197
    buffpek= queue.top();
1 by brian
clean slate
1198
    memcpy(param->unique_buff, buffpek->key, rec_length);
481 by Brian Aker
Remove all of uchar.
1199
    if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1 by brian
clean slate
1200
    {
971.6.11 by Eric Day
Removed purecov messages.
1201
      error=1; goto err;
1 by brian
clean slate
1202
    }
1203
    buffpek->key+= rec_length;
1204
    buffpek->mem_count--;
1205
    if (!--max_rows)
1206
    {
971.6.11 by Eric Day
Removed purecov messages.
1207
      error= 0;
1208
      goto end;
1 by brian
clean slate
1209
    }
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1210
    /* Top element has been used */
1211
    queue.pop();
1212
    queue.push(buffpek);
1 by brian
clean slate
1213
  }
1214
  else
1215
    cmp= 0;                                        // Not unique
1216
897.1.6 by Padraig
Cleaning up merge_buffers() function a little bit.
1217
  while (queue.size() > 1)
1 by brian
clean slate
1218
  {
1219
    if (*killed)
1220
    {
971.6.11 by Eric Day
Removed purecov messages.
1221
      error= 1; goto err;
1 by brian
clean slate
1222
    }
1223
    for (;;)
1224
    {
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1225
      buffpek= queue.top();
1 by brian
clean slate
1226
      if (cmp)                                        // Remove duplicates
1227
      {
1228
        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
481 by Brian Aker
Remove all of uchar.
1229
                    (unsigned char**) &buffpek->key))
1 by brian
clean slate
1230
              goto skip_duplicate;
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
1231
            memcpy(param->unique_buff, buffpek->key, rec_length);
1 by brian
clean slate
1232
      }
1233
      if (flag == 0)
1234
      {
481 by Brian Aker
Remove all of uchar.
1235
        if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1 by brian
clean slate
1236
        {
971.6.11 by Eric Day
Removed purecov messages.
1237
          error=1; goto err;
1 by brian
clean slate
1238
        }
1239
      }
1240
      else
1241
      {
481 by Brian Aker
Remove all of uchar.
1242
        if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1 by brian
clean slate
1243
        {
971.6.11 by Eric Day
Removed purecov messages.
1244
          error=1; goto err;
1 by brian
clean slate
1245
        }
1246
      }
1247
      if (!--max_rows)
1248
      {
971.6.11 by Eric Day
Removed purecov messages.
1249
        error= 0;
1250
        goto end;
1 by brian
clean slate
1251
      }
1252
1253
    skip_duplicate:
1254
      buffpek->key+= rec_length;
1255
      if (! --buffpek->mem_count)
1256
      {
1257
        if (!(error= (int) read_to_buffer(from_file,buffpek,
1258
                                          rec_length)))
1259
        {
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1260
          queue.pop();
1 by brian
clean slate
1261
          break;                        /* One buffer have been removed */
1262
        }
1263
        else if (error == -1)
971.6.11 by Eric Day
Removed purecov messages.
1264
          goto err;
1 by brian
clean slate
1265
      }
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1266
      /* Top element has been replaced */
1267
      queue.pop();
1268
      queue.push(buffpek);
1 by brian
clean slate
1269
    }
1270
  }
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1271
  buffpek= queue.top();
1 by brian
clean slate
1272
  buffpek->base= sort_buffer;
1273
  buffpek->max_keys= param->keys;
1274
1275
  /*
1276
    As we know all entries in the buffer are unique, we only have to
1277
    check if the first one is the same as the last one we wrote
1278
  */
1279
  if (cmp)
1280
  {
481 by Brian Aker
Remove all of uchar.
1281
    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1 by brian
clean slate
1282
    {
1283
      buffpek->key+= rec_length;         // Remove duplicate
1284
      --buffpek->mem_count;
1285
    }
1286
  }
1287
1288
  do
1289
  {
1290
    if ((ha_rows) buffpek->mem_count > max_rows)
1291
    {                                        /* Don't write too many records */
438.1.13 by Brian Aker
uint cleanup.
1292
      buffpek->mem_count= (uint32_t) max_rows;
1 by brian
clean slate
1293
      buffpek->count= 0;                        /* Don't read more */
1294
    }
1295
    max_rows-= buffpek->mem_count;
1296
    if (flag == 0)
1297
    {
481 by Brian Aker
Remove all of uchar.
1298
      if (my_b_write(to_file,(unsigned char*) buffpek->key,
1 by brian
clean slate
1299
                     (rec_length*buffpek->mem_count)))
1300
      {
971.6.11 by Eric Day
Removed purecov messages.
1301
        error= 1; goto err;
1 by brian
clean slate
1302
      }
1303
    }
1304
    else
1305
    {
481 by Brian Aker
Remove all of uchar.
1306
      register unsigned char *end;
1 by brian
clean slate
1307
      strpos= buffpek->key+offset;
1308
      for (end= strpos+buffpek->mem_count*rec_length ;
1309
           strpos != end ;
1310
           strpos+= rec_length)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1311
      {
481 by Brian Aker
Remove all of uchar.
1312
        if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1 by brian
clean slate
1313
        {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1314
          error=1; goto err;
1 by brian
clean slate
1315
        }
1316
      }
1317
    }
1318
  }
1319
  while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1320
         != -1 && error != 0);
1321
1322
end:
1067.4.1 by Nathan Williams
First few changes at converting cmin to std::min.
1323
  lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1 by brian
clean slate
1324
  lastbuff->file_pos= to_start_filepos;
1325
err:
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1326
  return(error);
1 by brian
clean slate
1327
} /* merge_buffers */
1328
1329
1330
	/* Do a merge to output-file (save only positions) */
1331
481 by Brian Aker
Remove all of uchar.
1332
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
438.1.13 by Brian Aker
uint cleanup.
1333
		       BUFFPEK *buffpek, uint32_t maxbuffer,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1334
		       internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1 by brian
clean slate
1335
{
1336
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1337
		    buffpek+maxbuffer,1))
971.6.11 by Eric Day
Removed purecov messages.
1338
    return(1);
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1339
  return(0);
1 by brian
clean slate
1340
} /* merge_index */
1341
1342
438.1.13 by Brian Aker
uint cleanup.
1343
static uint32_t suffix_length(uint32_t string_length)
1 by brian
clean slate
1344
{
1345
  if (string_length < 256)
1346
    return 1;
1347
  if (string_length < 256L*256L)
1348
    return 2;
1349
  if (string_length < 256L*256L*256L)
1350
    return 3;
1351
  return 4;                                     // Can't sort longer than 4G
1352
}
1353
1354
1355
1356
/**
1357
  Calculate length of sort key.
1358
1183.1.2 by Brian Aker
Rename of handler to Cursor. You would not believe how long I have wanted
1359
  @param session			  Thread Cursor
1 by brian
clean slate
1360
  @param sortorder		  Order of items to sort
1361
  @param s_length	          Number of items to sort
1362
  @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1363
                                 (In which case we have to use strxnfrm())
1364
1365
  @note
1366
    sortorder->length is updated for each sort item.
1367
  @n
1368
    sortorder->need_strxnfrm is set 1 if we have to use strxnfrm
1369
1370
  @return
1371
    Total length of sort buffer in bytes
1372
*/
1373
438.1.13 by Brian Aker
uint cleanup.
1374
static uint32_t
520.1.22 by Brian Aker
Second pass of thd cleanup
1375
sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
1 by brian
clean slate
1376
           bool *multi_byte_charset)
1377
{
438.1.13 by Brian Aker
uint cleanup.
1378
  register uint32_t length;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
1379
  const CHARSET_INFO *cs;
1 by brian
clean slate
1380
  *multi_byte_charset= 0;
1381
1382
  length=0;
1383
  for (; s_length-- ; sortorder++)
1384
  {
1385
    sortorder->need_strxnfrm= 0;
1386
    sortorder->suffix_length= 0;
1387
    if (sortorder->field)
1388
    {
1389
      cs= sortorder->field->sort_charset();
1390
      sortorder->length= sortorder->field->sort_length();
1391
1392
      if (use_strnxfrm((cs=sortorder->field->sort_charset())))
1393
      {
1394
        sortorder->need_strxnfrm= 1;
1395
        *multi_byte_charset= 1;
1396
        sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1397
      }
1398
      if (sortorder->field->maybe_null())
1399
	length++;				// Place for NULL marker
1400
    }
1401
    else
1402
    {
1403
      sortorder->result_type= sortorder->item->result_type();
152 by Brian Aker
longlong replacement
1404
      if (sortorder->item->result_as_int64_t())
1 by brian
clean slate
1405
        sortorder->result_type= INT_RESULT;
1406
      switch (sortorder->result_type) {
1407
      case STRING_RESULT:
1408
	sortorder->length=sortorder->item->max_length;
892.2.2 by Monty Taylor
More solaris warnings.
1409
        set_if_smaller(sortorder->length,
910.4.4 by Stewart Smith
max_sort_length should be size_t everywhere. Causing numerous failures on SPARC and PowerPC due to strang value being retrieved in filesort. Basically, anything with filesort fails without this patch.
1410
                       session->variables.max_sort_length);
1 by brian
clean slate
1411
	if (use_strnxfrm((cs=sortorder->item->collation.collation)))
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1412
	{
1 by brian
clean slate
1413
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1414
	  sortorder->need_strxnfrm= 1;
1415
	  *multi_byte_charset= 1;
1416
	}
1417
        else if (cs == &my_charset_bin)
1418
        {
1419
          /* Store length last to be able to sort blob/varbinary */
1420
          sortorder->suffix_length= suffix_length(sortorder->length);
1421
          sortorder->length+= sortorder->suffix_length;
1422
        }
1423
	break;
1424
      case INT_RESULT:
152 by Brian Aker
longlong replacement
1425
	sortorder->length=8;			// Size of intern int64_t
1 by brian
clean slate
1426
	break;
1427
      case DECIMAL_RESULT:
1428
        sortorder->length=
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1429
          my_decimal_get_binary_size(sortorder->item->max_length -
1 by brian
clean slate
1430
                                     (sortorder->item->decimals ? 1 : 0),
1431
                                     sortorder->item->decimals);
1432
        break;
1433
      case REAL_RESULT:
1434
	sortorder->length=sizeof(double);
1435
	break;
1436
      case ROW_RESULT:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1437
      default:
1 by brian
clean slate
1438
	// This case should never be choosen
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1439
	assert(0);
1 by brian
clean slate
1440
	break;
1441
      }
1442
      if (sortorder->item->maybe_null)
1443
	length++;				// Place for NULL marker
1444
    }
892.2.2 by Monty Taylor
More solaris warnings.
1445
    set_if_smaller(sortorder->length,
1446
                   (size_t)session->variables.max_sort_length);
1 by brian
clean slate
1447
    length+=sortorder->length;
1448
  }
1449
  sortorder->field= (Field*) 0;			// end marker
1450
  return length;
1451
}
1452
1453
1454
/**
1455
  Get descriptors of fields appended to sorted fields and
1456
  calculate its total length.
1457
1458
  The function first finds out what fields are used in the result set.
1459
  Then it calculates the length of the buffer to store the values of
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1460
  these fields together with the value of sort values.
1 by brian
clean slate
1461
  If the calculated length is not greater than max_length_for_sort_data
1462
  the function allocates memory for an array of descriptors containing
1463
  layouts for the values of the non-sorted fields in the buffer and
1464
  fills them.
1465
520.1.22 by Brian Aker
Second pass of thd cleanup
1466
  @param session                 Current thread
1 by brian
clean slate
1467
  @param ptabfield           Array of references to the table fields
1468
  @param sortlength          Total length of sorted fields
1469
  @param[out] plength        Total length of appended fields
1470
1471
  @note
1472
    The null bits for the appended values are supposed to be put together
1473
    and stored the buffer just ahead of the value of the first field.
1474
1475
  @return
1476
    Pointer to the layout descriptors for the appended fields, if any
1477
  @retval
1478
    NULL   if we do not store field values with sort data.
1479
*/
1480
1481
static SORT_ADDON_FIELD *
520.1.22 by Brian Aker
Second pass of thd cleanup
1482
get_addon_fields(Session *session, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
1 by brian
clean slate
1483
{
1484
  Field **pfield;
1485
  Field *field;
1486
  SORT_ADDON_FIELD *addonf;
438.1.13 by Brian Aker
uint cleanup.
1487
  uint32_t length= 0;
1488
  uint32_t fields= 0;
1489
  uint32_t null_fields= 0;
1 by brian
clean slate
1490
1491
  /*
1492
    If there is a reference to a field in the query add it
1493
    to the the set of appended fields.
1494
    Note for future refinement:
1495
    This this a too strong condition.
1496
    Actually we need only the fields referred in the
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1497
    result set. And for some of them it makes sense to use
1 by brian
clean slate
1498
    the values directly from sorted fields.
1499
  */
1500
  *plength= 0;
1501
1502
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1503
  {
1003.1.12 by Brian Aker
Begin of abstract out the bitmap from direct reference.
1504
    if (!(field->isReadSet()))
1 by brian
clean slate
1505
      continue;
1506
    if (field->flags & BLOB_FLAG)
1507
      return 0;
1508
    length+= field->max_packed_col_length(field->pack_length());
1509
    if (field->maybe_null())
1510
      null_fields++;
1511
    fields++;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1512
  }
1 by brian
clean slate
1513
  if (!fields)
1514
    return 0;
1515
  length+= (null_fields+7)/8;
1516
520.1.22 by Brian Aker
Second pass of thd cleanup
1517
  if (length+sortlength > session->variables.max_length_for_sort_data ||
641.3.7 by Monty Taylor
More my_malloc removal.
1518
      !(addonf= (SORT_ADDON_FIELD *) malloc(sizeof(SORT_ADDON_FIELD)*
1519
                                            (fields+1))))
1 by brian
clean slate
1520
    return 0;
1521
1522
  *plength= length;
1523
  length= (null_fields+7)/8;
1524
  null_fields= 0;
1525
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1526
  {
1003.1.12 by Brian Aker
Begin of abstract out the bitmap from direct reference.
1527
    if (!(field->isReadSet()))
1 by brian
clean slate
1528
      continue;
1529
    addonf->field= field;
1530
    addonf->offset= length;
1531
    if (field->maybe_null())
1532
    {
1533
      addonf->null_offset= null_fields/8;
1534
      addonf->null_bit= 1<<(null_fields & 7);
1535
      null_fields++;
1536
    }
1537
    else
1538
    {
1539
      addonf->null_offset= 0;
1540
      addonf->null_bit= 0;
1541
    }
1542
    addonf->length= field->max_packed_col_length(field->pack_length());
1543
    length+= addonf->length;
1544
    addonf++;
1545
  }
1546
  addonf->field= 0;     // Put end marker
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1547
1 by brian
clean slate
1548
  return (addonf-fields);
1549
}
1550
1551
1552
/**
1553
  Copy (unpack) values appended to sorted fields from a buffer back to
1554
  their regular positions specified by the Field::ptr pointers.
1555
1556
  @param addon_field     Array of descriptors for appended fields
1557
  @param buff            Buffer which to unpack the value from
1558
1559
  @note
1560
    The function is supposed to be used only as a callback function
1561
    when getting field values for the sorted result set.
1562
1563
  @return
1564
    void.
1565
*/
1566
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1567
static void
481 by Brian Aker
Remove all of uchar.
1568
unpack_addon_fields(struct st_sort_addon_field *addon_field, unsigned char *buff)
1 by brian
clean slate
1569
{
1570
  Field *field;
1571
  SORT_ADDON_FIELD *addonf= addon_field;
1572
1573
  for ( ; (field= addonf->field) ; addonf++)
1574
  {
1575
    if (addonf->null_bit && (addonf->null_bit & buff[addonf->null_offset]))
1576
    {
1577
      field->set_null();
1578
      continue;
1579
    }
1580
    field->set_notnull();
1581
    field->unpack(field->ptr, buff + addonf->offset);
1582
  }
1583
}
1584
1585
/*
1586
** functions to change a double or float to a sortable string
1587
** The following should work for IEEE
1588
*/
1589
1590
#define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
1591
481 by Brian Aker
Remove all of uchar.
1592
void change_double_for_sort(double nr,unsigned char *to)
1 by brian
clean slate
1593
{
481 by Brian Aker
Remove all of uchar.
1594
  unsigned char *tmp=(unsigned char*) to;
1 by brian
clean slate
1595
  if (nr == 0.0)
1596
  {						/* Change to zero string */
481 by Brian Aker
Remove all of uchar.
1597
    tmp[0]=(unsigned char) 128;
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
1598
    memset(tmp+1, 0, sizeof(nr)-1);
1 by brian
clean slate
1599
  }
1600
  else
1601
  {
1602
#ifdef WORDS_BIGENDIAN
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
1603
    memcpy(tmp,&nr,sizeof(nr));
1 by brian
clean slate
1604
#else
1605
    {
481 by Brian Aker
Remove all of uchar.
1606
      unsigned char *ptr= (unsigned char*) &nr;
1 by brian
clean slate
1607
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
1608
      tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
1609
      tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
1610
#else
1611
      tmp[0]= ptr[7]; tmp[1]=ptr[6]; tmp[2]= ptr[5]; tmp[3]=ptr[4];
1612
      tmp[4]= ptr[3]; tmp[5]=ptr[2]; tmp[6]= ptr[1]; tmp[7]=ptr[0];
1613
#endif
1614
    }
1615
#endif
1616
    if (tmp[0] & 128)				/* Negative */
1617
    {						/* make complement */
438.1.13 by Brian Aker
uint cleanup.
1618
      uint32_t i;
1 by brian
clean slate
1619
      for (i=0 ; i < sizeof(nr); i++)
481 by Brian Aker
Remove all of uchar.
1620
	tmp[i]=tmp[i] ^ (unsigned char) 255;
1 by brian
clean slate
1621
    }
1622
    else
1623
    {					/* Set high and move exponent one up */
438.1.13 by Brian Aker
uint cleanup.
1624
      uint16_t exp_part=(((uint16_t) tmp[0] << 8) | (uint16_t) tmp[1] |
1625
		       (uint16_t) 32768);
1626
      exp_part+= (uint16_t) 1 << (16-1-DBL_EXP_DIG);
481 by Brian Aker
Remove all of uchar.
1627
      tmp[0]= (unsigned char) (exp_part >> 8);
1628
      tmp[1]= (unsigned char) exp_part;
1 by brian
clean slate
1629
    }
1630
  }
1631
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1632
1633
} /* namespace drizzled */