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