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