~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;
218
    old_memavl=memavl;
219
    if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
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;
456
  MY_BITMAP *save_read_set, *save_write_set;
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 */
492
  bitmap_clear_all(&sort_form->tmp_set);
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
        if (!error)
527
          update_virtual_fields_marked_for_write(sort_form);
528
1 by brian
clean slate
529
	if (!flag)
530
	{
531
	  my_store_ptr(ref_pos,ref_length,record); // Position to row
532
	  record+= sort_form->s->db_record_offset;
533
	}
534
	else if (!error)
535
	  file->position(sort_form->record[0]);
536
      }
537
      if (error && error != HA_ERR_RECORD_DELETED)
538
	break;
539
    }
540
541
    if (*killed)
542
    {
543
      if (!indexfile && !quick_select)
544
      {
545
        (void) file->extra(HA_EXTRA_NO_CACHE);
546
        file->ha_rnd_end();
547
      }
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
548
      return(HA_POS_ERROR);		/* purecov: inspected */
1 by brian
clean slate
549
    }
550
    if (error == 0)
551
      param->examined_rows++;
552
    if (error == 0 && (!select || select->skip_record() == 0))
553
    {
554
      if (idx == param->keys)
555
      {
556
	if (write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
557
	  return(HA_POS_ERROR);
1 by brian
clean slate
558
	idx=0;
559
	indexpos++;
560
      }
561
      make_sortkey(param,sort_keys[idx++],ref_pos);
562
    }
563
    else
564
      file->unlock_row();
565
    /* 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
566
    if (session->is_error())
1 by brian
clean slate
567
      break;
568
  }
569
  if (quick_select)
570
  {
571
    /*
572
      index_merge quick select uses table->sort when retrieving rows, so free
573
      resoures it has allocated.
574
    */
575
    end_read_record(&read_record_info);
576
  }
577
  else
578
  {
579
    (void) file->extra(HA_EXTRA_NO_CACHE);	/* End cacheing of records */
580
    if (!next_pos)
581
      file->ha_rnd_end();
582
  }
583
520.1.22 by Brian Aker
Second pass of thd cleanup
584
  if (session->is_error())
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
585
    return(HA_POS_ERROR);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
586
1 by brian
clean slate
587
  /* Signal we should use orignal column read and write maps */
588
  sort_form->column_bitmaps_set(save_read_set, save_write_set);
589
590
  if (error != HA_ERR_END_OF_FILE)
591
  {
592
    file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
593
    return(HA_POS_ERROR);			/* purecov: inspected */
1 by brian
clean slate
594
  }
595
  if (indexpos && idx &&
596
      write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
597
    return(HA_POS_ERROR);			/* purecov: inspected */
598
  return(my_b_inited(tempfile) ?
1 by brian
clean slate
599
	      (ha_rows) (my_b_tell(tempfile)/param->rec_length) :
600
	      idx);
601
} /* find_all_keys */
602
603
604
/**
605
  @details
606
  Sort the buffer and write:
607
  -# the sorted sequence to tempfile
608
  -# a BUFFPEK describing the sorted sequence position to buffpek_pointers
609
610
    (was: Skriver en buffert med nycklar till filen)
611
612
  @param param             Sort parameters
613
  @param sort_keys         Array of pointers to keys to sort
614
  @param count             Number of elements in sort_keys array
615
  @param buffpek_pointers  One 'BUFFPEK' struct will be written into this file.
616
                           The BUFFPEK::{file_pos, count} will indicate where
617
                           the sorted data was stored.
618
  @param tempfile          The sorted sequence will be written into this file.
619
620
  @retval
621
    0 OK
622
  @retval
623
    1 Error
624
*/
625
626
static int
481 by Brian Aker
Remove all of uchar.
627
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
1 by brian
clean slate
628
           IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
629
{
630
  size_t sort_length, rec_length;
481 by Brian Aker
Remove all of uchar.
631
  unsigned char **end;
1 by brian
clean slate
632
  BUFFPEK buffpek;
633
634
  sort_length= param->sort_length;
635
  rec_length= param->rec_length;
481 by Brian Aker
Remove all of uchar.
636
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1 by brian
clean slate
637
  if (!my_b_inited(tempfile) &&
575.4.3 by ysano
Rename mysql to drizzle.
638
      open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
1 by brian
clean slate
639
                       MYF(MY_WME)))
640
    goto err;                                   /* purecov: inspected */
641
  /* check we won't have more buffpeks than we can possibly keep in memory */
151 by Brian Aker
Ulonglong to uint64_t
642
  if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
1 by brian
clean slate
643
    goto err;
644
  buffpek.file_pos= my_b_tell(tempfile);
645
  if ((ha_rows) count > param->max_rows)
438.1.13 by Brian Aker
uint cleanup.
646
    count=(uint32_t) param->max_rows;               /* purecov: inspected */
1 by brian
clean slate
647
  buffpek.count=(ha_rows) count;
648
  for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
481 by Brian Aker
Remove all of uchar.
649
    if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
1 by brian
clean slate
650
      goto err;
481 by Brian Aker
Remove all of uchar.
651
  if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
1 by brian
clean slate
652
    goto err;
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
653
  return(0);
1 by brian
clean slate
654
655
err:
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
656
  return(1);
1 by brian
clean slate
657
} /* write_keys */
658
659
660
/**
661
  Store length as suffix in high-byte-first order.
662
*/
663
481 by Brian Aker
Remove all of uchar.
664
static inline void store_length(unsigned char *to, uint32_t length, uint32_t pack_length)
1 by brian
clean slate
665
{
666
  switch (pack_length) {
667
  case 1:
481 by Brian Aker
Remove all of uchar.
668
    *to= (unsigned char) length;
1 by brian
clean slate
669
    break;
670
  case 2:
671
    mi_int2store(to, length);
672
    break;
673
  case 3:
674
    mi_int3store(to, length);
675
    break;
676
  default:
677
    mi_int4store(to, length);
678
    break;
679
  }
680
}
681
682
683
/** Make a sort-key from record. */
684
685
static void make_sortkey(register SORTPARAM *param,
481 by Brian Aker
Remove all of uchar.
686
			 register unsigned char *to, unsigned char *ref_pos)
1 by brian
clean slate
687
{
688
  register Field *field;
689
  register SORT_FIELD *sort_field;
937.2.7 by Stewart Smith
typesafe set_if_smaller/set_if_greater fixes from Solaris
690
  size_t length;
1 by brian
clean slate
691
692
  for (sort_field=param->local_sortorder ;
693
       sort_field != param->end ;
694
       sort_field++)
695
  {
696
    bool maybe_null=0;
697
    if ((field=sort_field->field))
698
    {						// Field
699
      if (field->maybe_null())
700
      {
701
	if (field->is_null())
702
	{
703
	  if (sort_field->reverse)
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
704
	    memset(to, 255, sort_field->length+1);
1 by brian
clean slate
705
	  else
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
706
	    memset(to, 0, sort_field->length+1);
1 by brian
clean slate
707
	  to+= sort_field->length+1;
708
	  continue;
709
	}
710
	else
711
	  *to++=1;
712
      }
713
      field->sort_string(to, sort_field->length);
714
    }
715
    else
716
    {						// Item
717
      Item *item=sort_field->item;
718
      maybe_null= item->maybe_null;
719
      switch (sort_field->result_type) {
720
      case STRING_RESULT:
721
      {
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
722
        const CHARSET_INFO * const cs=item->collation.collation;
1 by brian
clean slate
723
        char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
724
        int diff;
438.1.13 by Brian Aker
uint cleanup.
725
        uint32_t sort_field_length;
1 by brian
clean slate
726
727
        if (maybe_null)
728
          *to++=1;
729
        /* All item->str() to use some extra byte for end null.. */
730
        String tmp((char*) to,sort_field->length+4,cs);
731
        String *res= item->str_result(&tmp);
732
        if (!res)
733
        {
734
          if (maybe_null)
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
735
            memset(to-1, 0, sort_field->length+1);
1 by brian
clean slate
736
          else
737
          {
738
            /* purecov: begin deadcode */
739
            /*
740
              This should only happen during extreme conditions if we run out
741
              of memory or have an item marked not null when it can be null.
742
              This code is here mainly to avoid a hard crash in this case.
743
            */
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
744
            assert(0);
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
745
            memset(to, 0, sort_field->length);	// Avoid crash
1 by brian
clean slate
746
            /* purecov: end */
747
          }
748
          break;
749
        }
750
        length= res->length();
751
        sort_field_length= sort_field->length - sort_field->suffix_length;
752
        diff=(int) (sort_field_length - length);
753
        if (diff < 0)
754
        {
755
          diff=0;
756
          length= sort_field_length;
757
        }
758
        if (sort_field->suffix_length)
759
        {
760
          /* Store length last in result_string */
761
          store_length(to + sort_field_length, length,
762
                       sort_field->suffix_length);
763
        }
764
        if (sort_field->need_strxnfrm)
765
        {
766
          char *from=(char*) res->ptr();
438.1.13 by Brian Aker
uint cleanup.
767
          uint32_t tmp_length;
481 by Brian Aker
Remove all of uchar.
768
          if ((unsigned char*) from == to)
1 by brian
clean slate
769
          {
770
            set_if_smaller(length,sort_field->length);
771
            memcpy(param->tmp_buffer,from,length);
772
            from=param->tmp_buffer;
773
          }
774
          tmp_length= my_strnxfrm(cs,to,sort_field->length,
481 by Brian Aker
Remove all of uchar.
775
                                  (unsigned char*) from, length);
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
776
          assert(tmp_length == sort_field->length);
1 by brian
clean slate
777
        }
778
        else
779
        {
481 by Brian Aker
Remove all of uchar.
780
          my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
1 by brian
clean slate
781
          cs->cset->fill(cs, (char *)to+length,diff,fill_char);
782
        }
783
        break;
784
      }
785
      case INT_RESULT:
786
	{
152 by Brian Aker
longlong replacement
787
          int64_t value= item->val_int_result();
1 by brian
clean slate
788
          if (maybe_null)
789
          {
790
	    *to++=1;				/* purecov: inspected */
791
            if (item->null_value)
792
            {
793
              if (maybe_null)
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
794
                memset(to-1, 0, sort_field->length+1);
1 by brian
clean slate
795
              else
796
              {
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
797
                memset(to, 0, sort_field->length);
1 by brian
clean slate
798
              }
799
              break;
800
            }
801
          }
481 by Brian Aker
Remove all of uchar.
802
	  to[7]= (unsigned char) value;
803
	  to[6]= (unsigned char) (value >> 8);
804
	  to[5]= (unsigned char) (value >> 16);
805
	  to[4]= (unsigned char) (value >> 24);
806
	  to[3]= (unsigned char) (value >> 32);
807
	  to[2]= (unsigned char) (value >> 40);
808
	  to[1]= (unsigned char) (value >> 48);
1 by brian
clean slate
809
          if (item->unsigned_flag)                    /* Fix sign */
481 by Brian Aker
Remove all of uchar.
810
            to[0]= (unsigned char) (value >> 56);
1 by brian
clean slate
811
          else
481 by Brian Aker
Remove all of uchar.
812
            to[0]= (unsigned char) (value >> 56) ^ 128;	/* Reverse signbit */
1 by brian
clean slate
813
	  break;
814
	}
815
      case DECIMAL_RESULT:
816
        {
817
          my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
818
          if (maybe_null)
819
          {
820
            if (item->null_value)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
821
            {
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
822
              memset(to, 0, sort_field->length+1);
1 by brian
clean slate
823
              to++;
824
              break;
825
            }
826
            *to++=1;
827
          }
828
          my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to,
829
                            item->max_length - (item->decimals ? 1:0),
830
                            item->decimals);
831
         break;
832
        }
833
      case REAL_RESULT:
834
	{
835
          double value= item->val_result();
836
	  if (maybe_null)
837
          {
838
            if (item->null_value)
839
            {
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
840
              memset(to, 0, sort_field->length+1);
1 by brian
clean slate
841
              to++;
842
              break;
843
            }
844
	    *to++=1;
845
          }
481 by Brian Aker
Remove all of uchar.
846
	  change_double_for_sort(value,(unsigned char*) to);
1 by brian
clean slate
847
	  break;
848
	}
849
      case ROW_RESULT:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
850
      default:
1 by brian
clean slate
851
	// This case should never be choosen
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
852
	assert(0);
1 by brian
clean slate
853
	break;
854
      }
855
    }
856
    if (sort_field->reverse)
857
    {							/* Revers key */
858
      if (maybe_null)
859
        to[-1]= ~to[-1];
860
      length=sort_field->length;
861
      while (length--)
862
      {
481 by Brian Aker
Remove all of uchar.
863
	*to = (unsigned char) (~ *to);
1 by brian
clean slate
864
	to++;
865
      }
866
    }
867
    else
868
      to+= sort_field->length;
869
  }
870
871
  if (param->addon_field)
872
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
873
    /*
1 by brian
clean slate
874
      Save field values appended to sorted fields.
875
      First null bit indicators are appended then field values follow.
876
      In this implementation we use fixed layout for field values -
877
      the same for all records.
878
    */
879
    SORT_ADDON_FIELD *addonf= param->addon_field;
481 by Brian Aker
Remove all of uchar.
880
    unsigned char *nulls= to;
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
881
    assert(addonf != 0);
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
882
    memset(nulls, 0, addonf->offset);
1 by brian
clean slate
883
    to+= addonf->offset;
884
    for ( ; (field= addonf->field) ; addonf++)
885
    {
886
      if (addonf->null_bit && field->is_null())
887
      {
888
        nulls[addonf->null_offset]|= addonf->null_bit;
889
#ifdef HAVE_purify
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
890
	memset(to, 0, addonf->length);
1 by brian
clean slate
891
#endif
892
      }
893
      else
894
      {
895
#ifdef HAVE_purify
481 by Brian Aker
Remove all of uchar.
896
        unsigned char *end= field->pack(to, field->ptr);
438.1.13 by Brian Aker
uint cleanup.
897
	uint32_t length= (uint32_t) ((to + addonf->length) - end);
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
898
	assert((int) length >= 0);
1 by brian
clean slate
899
	if (length)
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
900
	  memset(end, 0, length);
1 by brian
clean slate
901
#else
902
        (void) field->pack(to, field->ptr);
903
#endif
904
      }
905
      to+= addonf->length;
906
    }
907
  }
908
  else
909
  {
910
    /* Save filepos last */
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
911
    memcpy(to, ref_pos, (size_t) param->ref_length);
1 by brian
clean slate
912
  }
913
  return;
914
}
915
916
917
/*
918
  Register fields used by sorting in the sorted table's read set
919
*/
920
921
static void register_used_fields(SORTPARAM *param)
922
{
923
  register SORT_FIELD *sort_field;
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
924
  Table *table=param->sort_form;
1 by brian
clean slate
925
  MY_BITMAP *bitmap= table->read_set;
926
927
  for (sort_field= param->local_sortorder ;
928
       sort_field != param->end ;
929
       sort_field++)
930
  {
931
    Field *field;
932
    if ((field= sort_field->field))
933
    {
934
      if (field->table == table)
935
      bitmap_set_bit(bitmap, field->field_index);
936
    }
937
    else
938
    {						// Item
939
      sort_field->item->walk(&Item::register_field_in_read_map, 1,
481 by Brian Aker
Remove all of uchar.
940
                             (unsigned char *) table);
1 by brian
clean slate
941
    }
942
  }
943
944
  if (param->addon_field)
945
  {
946
    SORT_ADDON_FIELD *addonf= param->addon_field;
947
    Field *field;
948
    for ( ; (field= addonf->field) ; addonf++)
949
      bitmap_set_bit(bitmap, field->field_index);
950
  }
951
  else
952
  {
953
    /* Save filepos last */
954
    table->prepare_for_position();
955
  }
956
}
957
958
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
959
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
327.2.3 by Brian Aker
Refactoring of class Table
960
                       filesort_info_st *table_sort)
1 by brian
clean slate
961
{
438.1.13 by Brian Aker
uint cleanup.
962
  uint32_t offset,res_length;
481 by Brian Aker
Remove all of uchar.
963
  unsigned char *to;
1 by brian
clean slate
964
481 by Brian Aker
Remove all of uchar.
965
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
1 by brian
clean slate
966
  res_length= param->res_length;
967
  offset= param->rec_length-res_length;
968
  if ((ha_rows) count > param->max_rows)
438.1.13 by Brian Aker
uint cleanup.
969
    count=(uint32_t) param->max_rows;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
970
  if (!(to= table_sort->record_pointers=
641.3.7 by Monty Taylor
More my_malloc removal.
971
        (unsigned char*) malloc(res_length*count)))
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
972
    return(1);                 /* purecov: inspected */
481 by Brian Aker
Remove all of uchar.
973
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1 by brian
clean slate
974
  {
975
    memcpy(to, *sort_keys+offset, res_length);
976
    to+= res_length;
977
  }
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
978
  return(0);
1 by brian
clean slate
979
}
980
981
982
/** Merge buffers to make < MERGEBUFF2 buffers. */
983
481 by Brian Aker
Remove all of uchar.
984
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
438.1.13 by Brian Aker
uint cleanup.
985
		    BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1 by brian
clean slate
986
{
438.1.13 by Brian Aker
uint cleanup.
987
  register uint32_t i;
1 by brian
clean slate
988
  IO_CACHE t_file2,*from_file,*to_file,*temp;
989
  BUFFPEK *lastbuff;
990
991
  if (*maxbuffer < MERGEBUFF2)
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
992
    return(0);				/* purecov: inspected */
1 by brian
clean slate
993
  if (flush_io_cache(t_file) ||
575.4.3 by ysano
Rename mysql to drizzle.
994
      open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
1 by brian
clean slate
995
			MYF(MY_WME)))
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
996
    return(1);				/* purecov: inspected */
1 by brian
clean slate
997
998
  from_file= t_file ; to_file= &t_file2;
999
  while (*maxbuffer >= MERGEBUFF2)
1000
  {
1001
    if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
1002
      goto cleanup;
1003
    if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
1004
      goto cleanup;
1005
    lastbuff=buffpek;
1006
    for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1007
    {
1008
      if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1009
			buffpek+i,buffpek+i+MERGEBUFF-1,0))
1010
      goto cleanup;
1011
    }
1012
    if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1013
		      buffpek+i,buffpek+ *maxbuffer,0))
1014
      break;					/* purecov: inspected */
1015
    if (flush_io_cache(to_file))
1016
      break;					/* purecov: inspected */
1017
    temp=from_file; from_file=to_file; to_file=temp;
1018
    setup_io_cache(from_file);
1019
    setup_io_cache(to_file);
438.1.13 by Brian Aker
uint cleanup.
1020
    *maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1 by brian
clean slate
1021
  }
1022
cleanup:
1023
  close_cached_file(to_file);			// This holds old result
1024
  if (to_file == t_file)
1025
  {
1026
    *t_file=t_file2;				// Copy result file
1027
    setup_io_cache(t_file);
1028
  }
1029
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1030
  return(*maxbuffer >= MERGEBUFF2);	/* Return 1 if interrupted */
1 by brian
clean slate
1031
} /* merge_many_buff */
1032
1033
1034
/**
1035
  Read data to buffer.
1036
1037
  @retval
438.1.13 by Brian Aker
uint cleanup.
1038
    (uint32_t)-1 if something goes wrong
1 by brian
clean slate
1039
*/
1040
438.1.13 by Brian Aker
uint cleanup.
1041
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1042
		    uint32_t rec_length)
1 by brian
clean slate
1043
{
438.1.13 by Brian Aker
uint cleanup.
1044
  register uint32_t count;
1045
  uint32_t length;
1 by brian
clean slate
1046
438.1.13 by Brian Aker
uint cleanup.
1047
  if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1 by brian
clean slate
1048
  {
481 by Brian Aker
Remove all of uchar.
1049
    if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
438.1.13 by Brian Aker
uint cleanup.
1050
      return((uint32_t) -1);			/* purecov: inspected */
1 by brian
clean slate
1051
    buffpek->key=buffpek->base;
1052
    buffpek->file_pos+= length;			/* New filepos */
1053
    buffpek->count-=	count;
1054
    buffpek->mem_count= count;
1055
  }
1056
  return (count*rec_length);
1057
} /* read_to_buffer */
1058
1059
897.1.11 by Padraig
Giving function object a better name for this scenario.
1060
class compare_functor
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1061
{
897.1.6 by Padraig
Cleaning up merge_buffers() function a little bit.
1062
  qsort2_cmp key_compare;
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1063
  void *key_compare_arg;
1064
  public:
897.1.11 by Padraig
Giving function object a better name for this scenario.
1065
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
897.1.6 by Padraig
Cleaning up merge_buffers() function a little bit.
1066
    : 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
1067
  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
1068
  {
897.1.16 by Padraig O'Sullivan
Cleaning up my function object. Making it const correct and putting
1069
    int val= key_compare(key_compare_arg,
1070
                      &i->key, &j->key);
897.1.18 by Padraig O'Sullivan
Cleaning up my function object a little bit.
1071
    return (val >= 0);
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1072
  }
1073
};
1074
1 by brian
clean slate
1075
1076
/**
1077
  Merge buffers to one buffer.
1078
1079
  @param param        Sort parameter
1080
  @param from_file    File with source data (BUFFPEKs point to this file)
1081
  @param to_file      File to write the sorted result data.
1082
  @param sort_buffer  Buffer for data to store up to MERGEBUFF2 sort keys.
1083
  @param lastbuff     OUT Store here BUFFPEK describing data written to to_file
1084
  @param Fb           First element in source BUFFPEKs array
1085
  @param Tb           Last element in source BUFFPEKs array
1086
  @param flag
1087
1088
  @retval
1089
    0      OK
1090
  @retval
1091
    other  error
1092
*/
1093
1094
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
481 by Brian Aker
Remove all of uchar.
1095
                  IO_CACHE *to_file, unsigned char *sort_buffer,
1 by brian
clean slate
1096
                  BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1097
                  int flag)
1098
{
1099
  int error;
438.1.13 by Brian Aker
uint cleanup.
1100
  uint32_t rec_length,res_length,offset;
1 by brian
clean slate
1101
  size_t sort_length;
308 by Brian Aker
ulong conversion
1102
  uint32_t maxcount;
1 by brian
clean slate
1103
  ha_rows max_rows,org_max_rows;
1104
  my_off_t to_start_filepos;
481 by Brian Aker
Remove all of uchar.
1105
  unsigned char *strpos;
1 by brian
clean slate
1106
  BUFFPEK *buffpek;
1107
  qsort2_cmp cmp;
1108
  void *first_cmp_arg;
520.1.22 by Brian Aker
Second pass of thd cleanup
1109
  volatile Session::killed_state *killed= &current_session->killed;
520.1.21 by Brian Aker
THD -> Session rename
1110
  Session::killed_state not_killable;
1 by brian
clean slate
1111
520.1.22 by Brian Aker
Second pass of thd cleanup
1112
  status_var_increment(current_session->status_var.filesort_merge_passes);
1 by brian
clean slate
1113
  if (param->not_killable)
1114
  {
1115
    killed= &not_killable;
520.1.21 by Brian Aker
THD -> Session rename
1116
    not_killable= Session::NOT_KILLED;
1 by brian
clean slate
1117
  }
1118
1119
  error=0;
1120
  rec_length= param->rec_length;
1121
  res_length= param->res_length;
1122
  sort_length= param->sort_length;
1123
  offset= rec_length-res_length;
438.1.13 by Brian Aker
uint cleanup.
1124
  maxcount= (uint32_t) (param->keys/((uint32_t) (Tb-Fb) +1));
1 by brian
clean slate
1125
  to_start_filepos= my_b_tell(to_file);
481 by Brian Aker
Remove all of uchar.
1126
  strpos= (unsigned char*) sort_buffer;
1 by brian
clean slate
1127
  org_max_rows=max_rows= param->max_rows;
1128
1129
  /* The following will fire if there is not enough space in sort_buffer */
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1130
  assert(maxcount!=0);
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1131
1 by brian
clean slate
1132
  if (param->unique_buff)
1133
  {
1134
    cmp= param->compare;
1135
    first_cmp_arg= (void *) &param->cmp_context;
1136
  }
1137
  else
1138
  {
1139
    cmp= get_ptr_compare(sort_length);
1140
    first_cmp_arg= (void*) &sort_length;
1141
  }
897.1.11 by Padraig
Giving function object a better name for this scenario.
1142
  priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor > 
1143
    queue(compare_functor(cmp, first_cmp_arg));
1 by brian
clean slate
1144
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1145
  {
1146
    buffpek->base= strpos;
1147
    buffpek->max_keys= maxcount;
438.1.13 by Brian Aker
uint cleanup.
1148
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1 by brian
clean slate
1149
                                                                         rec_length));
1150
    if (error == -1)
1151
      goto err;					/* purecov: inspected */
1152
    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
1153
    queue.push(buffpek);
1 by brian
clean slate
1154
  }
1155
1156
  if (param->unique_buff)
1157
  {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1158
    /*
1 by brian
clean slate
1159
       Called by Unique::get()
1160
       Copy the first argument to param->unique_buff for unique removal.
1161
       Store it also in 'to_file'.
1162
1163
       This is safe as we know that there is always more than one element
1164
       in each block to merge (This is guaranteed by the Unique:: algorithm
1165
    */
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1166
    buffpek= queue.top();
1 by brian
clean slate
1167
    memcpy(param->unique_buff, buffpek->key, rec_length);
481 by Brian Aker
Remove all of uchar.
1168
    if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1 by brian
clean slate
1169
    {
1170
      error=1; goto err;                        /* purecov: inspected */
1171
    }
1172
    buffpek->key+= rec_length;
1173
    buffpek->mem_count--;
1174
    if (!--max_rows)
1175
    {
1176
      error= 0;                                       /* purecov: inspected */
1177
      goto end;                                       /* purecov: inspected */
1178
    }
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1179
    /* Top element has been used */
1180
    queue.pop();
1181
    queue.push(buffpek);
1 by brian
clean slate
1182
  }
1183
  else
1184
    cmp= 0;                                        // Not unique
1185
897.1.6 by Padraig
Cleaning up merge_buffers() function a little bit.
1186
  while (queue.size() > 1)
1 by brian
clean slate
1187
  {
1188
    if (*killed)
1189
    {
1190
      error= 1; goto err;                        /* purecov: inspected */
1191
    }
1192
    for (;;)
1193
    {
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1194
      buffpek= queue.top();
1 by brian
clean slate
1195
      if (cmp)                                        // Remove duplicates
1196
      {
1197
        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
481 by Brian Aker
Remove all of uchar.
1198
                    (unsigned char**) &buffpek->key))
1 by brian
clean slate
1199
              goto skip_duplicate;
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
1200
            memcpy(param->unique_buff, buffpek->key, rec_length);
1 by brian
clean slate
1201
      }
1202
      if (flag == 0)
1203
      {
481 by Brian Aker
Remove all of uchar.
1204
        if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1 by brian
clean slate
1205
        {
1206
          error=1; goto err;                        /* purecov: inspected */
1207
        }
1208
      }
1209
      else
1210
      {
481 by Brian Aker
Remove all of uchar.
1211
        if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1 by brian
clean slate
1212
        {
1213
          error=1; goto err;                        /* purecov: inspected */
1214
        }
1215
      }
1216
      if (!--max_rows)
1217
      {
1218
        error= 0;                               /* purecov: inspected */
1219
        goto end;                               /* purecov: inspected */
1220
      }
1221
1222
    skip_duplicate:
1223
      buffpek->key+= rec_length;
1224
      if (! --buffpek->mem_count)
1225
      {
1226
        if (!(error= (int) read_to_buffer(from_file,buffpek,
1227
                                          rec_length)))
1228
        {
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1229
          queue.pop();
1 by brian
clean slate
1230
          break;                        /* One buffer have been removed */
1231
        }
1232
        else if (error == -1)
1233
          goto err;                        /* purecov: inspected */
1234
      }
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1235
      /* Top element has been replaced */
1236
      queue.pop();
1237
      queue.push(buffpek);
1 by brian
clean slate
1238
    }
1239
  }
897.1.5 by Padraig
Replacing the instance of QUEUE in the merge_buffers() function in
1240
  buffpek= queue.top();
1 by brian
clean slate
1241
  buffpek->base= sort_buffer;
1242
  buffpek->max_keys= param->keys;
1243
1244
  /*
1245
    As we know all entries in the buffer are unique, we only have to
1246
    check if the first one is the same as the last one we wrote
1247
  */
1248
  if (cmp)
1249
  {
481 by Brian Aker
Remove all of uchar.
1250
    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1 by brian
clean slate
1251
    {
1252
      buffpek->key+= rec_length;         // Remove duplicate
1253
      --buffpek->mem_count;
1254
    }
1255
  }
1256
1257
  do
1258
  {
1259
    if ((ha_rows) buffpek->mem_count > max_rows)
1260
    {                                        /* Don't write too many records */
438.1.13 by Brian Aker
uint cleanup.
1261
      buffpek->mem_count= (uint32_t) max_rows;
1 by brian
clean slate
1262
      buffpek->count= 0;                        /* Don't read more */
1263
    }
1264
    max_rows-= buffpek->mem_count;
1265
    if (flag == 0)
1266
    {
481 by Brian Aker
Remove all of uchar.
1267
      if (my_b_write(to_file,(unsigned char*) buffpek->key,
1 by brian
clean slate
1268
                     (rec_length*buffpek->mem_count)))
1269
      {
1270
        error= 1; goto err;                        /* purecov: inspected */
1271
      }
1272
    }
1273
    else
1274
    {
481 by Brian Aker
Remove all of uchar.
1275
      register unsigned char *end;
1 by brian
clean slate
1276
      strpos= buffpek->key+offset;
1277
      for (end= strpos+buffpek->mem_count*rec_length ;
1278
           strpos != end ;
1279
           strpos+= rec_length)
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1280
      {
481 by Brian Aker
Remove all of uchar.
1281
        if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1 by brian
clean slate
1282
        {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1283
          error=1; goto err;
1 by brian
clean slate
1284
        }
1285
      }
1286
    }
1287
  }
1288
  while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1289
         != -1 && error != 0);
1290
1291
end:
398.1.4 by Monty Taylor
Renamed max/min.
1292
  lastbuff->count= cmin(org_max_rows-max_rows, param->max_rows);
1 by brian
clean slate
1293
  lastbuff->file_pos= to_start_filepos;
1294
err:
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1295
  return(error);
1 by brian
clean slate
1296
} /* merge_buffers */
1297
1298
1299
	/* Do a merge to output-file (save only positions) */
1300
481 by Brian Aker
Remove all of uchar.
1301
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
438.1.13 by Brian Aker
uint cleanup.
1302
		       BUFFPEK *buffpek, uint32_t maxbuffer,
1 by brian
clean slate
1303
		       IO_CACHE *tempfile, IO_CACHE *outfile)
1304
{
1305
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1306
		    buffpek+maxbuffer,1))
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1307
    return(1);				/* purecov: inspected */
1308
  return(0);
1 by brian
clean slate
1309
} /* merge_index */
1310
1311
438.1.13 by Brian Aker
uint cleanup.
1312
static uint32_t suffix_length(uint32_t string_length)
1 by brian
clean slate
1313
{
1314
  if (string_length < 256)
1315
    return 1;
1316
  if (string_length < 256L*256L)
1317
    return 2;
1318
  if (string_length < 256L*256L*256L)
1319
    return 3;
1320
  return 4;                                     // Can't sort longer than 4G
1321
}
1322
1323
1324
1325
/**
1326
  Calculate length of sort key.
1327
520.1.22 by Brian Aker
Second pass of thd cleanup
1328
  @param session			  Thread handler
1 by brian
clean slate
1329
  @param sortorder		  Order of items to sort
1330
  @param s_length	          Number of items to sort
1331
  @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1332
                                 (In which case we have to use strxnfrm())
1333
1334
  @note
1335
    sortorder->length is updated for each sort item.
1336
  @n
1337
    sortorder->need_strxnfrm is set 1 if we have to use strxnfrm
1338
1339
  @return
1340
    Total length of sort buffer in bytes
1341
*/
1342
438.1.13 by Brian Aker
uint cleanup.
1343
static uint32_t
520.1.22 by Brian Aker
Second pass of thd cleanup
1344
sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
1 by brian
clean slate
1345
           bool *multi_byte_charset)
1346
{
438.1.13 by Brian Aker
uint cleanup.
1347
  register uint32_t length;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
1348
  const CHARSET_INFO *cs;
1 by brian
clean slate
1349
  *multi_byte_charset= 0;
1350
1351
  length=0;
1352
  for (; s_length-- ; sortorder++)
1353
  {
1354
    sortorder->need_strxnfrm= 0;
1355
    sortorder->suffix_length= 0;
1356
    if (sortorder->field)
1357
    {
1358
      cs= sortorder->field->sort_charset();
1359
      sortorder->length= sortorder->field->sort_length();
1360
1361
      if (use_strnxfrm((cs=sortorder->field->sort_charset())))
1362
      {
1363
        sortorder->need_strxnfrm= 1;
1364
        *multi_byte_charset= 1;
1365
        sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1366
      }
1367
      if (sortorder->field->maybe_null())
1368
	length++;				// Place for NULL marker
1369
    }
1370
    else
1371
    {
1372
      sortorder->result_type= sortorder->item->result_type();
152 by Brian Aker
longlong replacement
1373
      if (sortorder->item->result_as_int64_t())
1 by brian
clean slate
1374
        sortorder->result_type= INT_RESULT;
1375
      switch (sortorder->result_type) {
1376
      case STRING_RESULT:
1377
	sortorder->length=sortorder->item->max_length;
892.2.2 by Monty Taylor
More solaris warnings.
1378
        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.
1379
                       session->variables.max_sort_length);
1 by brian
clean slate
1380
	if (use_strnxfrm((cs=sortorder->item->collation.collation)))
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1381
	{
1 by brian
clean slate
1382
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1383
	  sortorder->need_strxnfrm= 1;
1384
	  *multi_byte_charset= 1;
1385
	}
1386
        else if (cs == &my_charset_bin)
1387
        {
1388
          /* Store length last to be able to sort blob/varbinary */
1389
          sortorder->suffix_length= suffix_length(sortorder->length);
1390
          sortorder->length+= sortorder->suffix_length;
1391
        }
1392
	break;
1393
      case INT_RESULT:
152 by Brian Aker
longlong replacement
1394
	sortorder->length=8;			// Size of intern int64_t
1 by brian
clean slate
1395
	break;
1396
      case DECIMAL_RESULT:
1397
        sortorder->length=
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1398
          my_decimal_get_binary_size(sortorder->item->max_length -
1 by brian
clean slate
1399
                                     (sortorder->item->decimals ? 1 : 0),
1400
                                     sortorder->item->decimals);
1401
        break;
1402
      case REAL_RESULT:
1403
	sortorder->length=sizeof(double);
1404
	break;
1405
      case ROW_RESULT:
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1406
      default:
1 by brian
clean slate
1407
	// This case should never be choosen
51.1.12 by Jay Pipes
Removed/replaced DBUG symbols
1408
	assert(0);
1 by brian
clean slate
1409
	break;
1410
      }
1411
      if (sortorder->item->maybe_null)
1412
	length++;				// Place for NULL marker
1413
    }
892.2.2 by Monty Taylor
More solaris warnings.
1414
    set_if_smaller(sortorder->length,
1415
                   (size_t)session->variables.max_sort_length);
1 by brian
clean slate
1416
    length+=sortorder->length;
1417
  }
1418
  sortorder->field= (Field*) 0;			// end marker
1419
  return length;
1420
}
1421
1422
1423
/**
1424
  Get descriptors of fields appended to sorted fields and
1425
  calculate its total length.
1426
1427
  The function first finds out what fields are used in the result set.
1428
  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:
1429
  these fields together with the value of sort values.
1 by brian
clean slate
1430
  If the calculated length is not greater than max_length_for_sort_data
1431
  the function allocates memory for an array of descriptors containing
1432
  layouts for the values of the non-sorted fields in the buffer and
1433
  fills them.
1434
520.1.22 by Brian Aker
Second pass of thd cleanup
1435
  @param session                 Current thread
1 by brian
clean slate
1436
  @param ptabfield           Array of references to the table fields
1437
  @param sortlength          Total length of sorted fields
1438
  @param[out] plength        Total length of appended fields
1439
1440
  @note
1441
    The null bits for the appended values are supposed to be put together
1442
    and stored the buffer just ahead of the value of the first field.
1443
1444
  @return
1445
    Pointer to the layout descriptors for the appended fields, if any
1446
  @retval
1447
    NULL   if we do not store field values with sort data.
1448
*/
1449
1450
static SORT_ADDON_FIELD *
520.1.22 by Brian Aker
Second pass of thd cleanup
1451
get_addon_fields(Session *session, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
1 by brian
clean slate
1452
{
1453
  Field **pfield;
1454
  Field *field;
1455
  SORT_ADDON_FIELD *addonf;
438.1.13 by Brian Aker
uint cleanup.
1456
  uint32_t length= 0;
1457
  uint32_t fields= 0;
1458
  uint32_t null_fields= 0;
1 by brian
clean slate
1459
  MY_BITMAP *read_set= (*ptabfield)->table->read_set;
1460
1461
  /*
1462
    If there is a reference to a field in the query add it
1463
    to the the set of appended fields.
1464
    Note for future refinement:
1465
    This this a too strong condition.
1466
    Actually we need only the fields referred in the
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1467
    result set. And for some of them it makes sense to use
1 by brian
clean slate
1468
    the values directly from sorted fields.
1469
  */
1470
  *plength= 0;
1471
1472
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1473
  {
1474
    if (!bitmap_is_set(read_set, field->field_index))
1475
      continue;
1476
    if (field->flags & BLOB_FLAG)
1477
      return 0;
1478
    length+= field->max_packed_col_length(field->pack_length());
1479
    if (field->maybe_null())
1480
      null_fields++;
1481
    fields++;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1482
  }
1 by brian
clean slate
1483
  if (!fields)
1484
    return 0;
1485
  length+= (null_fields+7)/8;
1486
520.1.22 by Brian Aker
Second pass of thd cleanup
1487
  if (length+sortlength > session->variables.max_length_for_sort_data ||
641.3.7 by Monty Taylor
More my_malloc removal.
1488
      !(addonf= (SORT_ADDON_FIELD *) malloc(sizeof(SORT_ADDON_FIELD)*
1489
                                            (fields+1))))
1 by brian
clean slate
1490
    return 0;
1491
1492
  *plength= length;
1493
  length= (null_fields+7)/8;
1494
  null_fields= 0;
1495
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1496
  {
1497
    if (!bitmap_is_set(read_set, field->field_index))
1498
      continue;
1499
    addonf->field= field;
1500
    addonf->offset= length;
1501
    if (field->maybe_null())
1502
    {
1503
      addonf->null_offset= null_fields/8;
1504
      addonf->null_bit= 1<<(null_fields & 7);
1505
      null_fields++;
1506
    }
1507
    else
1508
    {
1509
      addonf->null_offset= 0;
1510
      addonf->null_bit= 0;
1511
    }
1512
    addonf->length= field->max_packed_col_length(field->pack_length());
1513
    length+= addonf->length;
1514
    addonf++;
1515
  }
1516
  addonf->field= 0;     // Put end marker
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1517
1 by brian
clean slate
1518
  return (addonf-fields);
1519
}
1520
1521
1522
/**
1523
  Copy (unpack) values appended to sorted fields from a buffer back to
1524
  their regular positions specified by the Field::ptr pointers.
1525
1526
  @param addon_field     Array of descriptors for appended fields
1527
  @param buff            Buffer which to unpack the value from
1528
1529
  @note
1530
    The function is supposed to be used only as a callback function
1531
    when getting field values for the sorted result set.
1532
1533
  @return
1534
    void.
1535
*/
1536
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
1537
static void
481 by Brian Aker
Remove all of uchar.
1538
unpack_addon_fields(struct st_sort_addon_field *addon_field, unsigned char *buff)
1 by brian
clean slate
1539
{
1540
  Field *field;
1541
  SORT_ADDON_FIELD *addonf= addon_field;
1542
1543
  for ( ; (field= addonf->field) ; addonf++)
1544
  {
1545
    if (addonf->null_bit && (addonf->null_bit & buff[addonf->null_offset]))
1546
    {
1547
      field->set_null();
1548
      continue;
1549
    }
1550
    field->set_notnull();
1551
    field->unpack(field->ptr, buff + addonf->offset);
1552
  }
1553
}
1554
1555
/*
1556
** functions to change a double or float to a sortable string
1557
** The following should work for IEEE
1558
*/
1559
1560
#define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
1561
481 by Brian Aker
Remove all of uchar.
1562
void change_double_for_sort(double nr,unsigned char *to)
1 by brian
clean slate
1563
{
481 by Brian Aker
Remove all of uchar.
1564
  unsigned char *tmp=(unsigned char*) to;
1 by brian
clean slate
1565
  if (nr == 0.0)
1566
  {						/* Change to zero string */
481 by Brian Aker
Remove all of uchar.
1567
    tmp[0]=(unsigned char) 128;
212.6.6 by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove().
1568
    memset(tmp+1, 0, sizeof(nr)-1);
1 by brian
clean slate
1569
  }
1570
  else
1571
  {
1572
#ifdef WORDS_BIGENDIAN
212.6.3 by Mats Kindahl
Removing deprecated functions from code and replacing them with C99 equivalents:
1573
    memcpy(tmp,&nr,sizeof(nr));
1 by brian
clean slate
1574
#else
1575
    {
481 by Brian Aker
Remove all of uchar.
1576
      unsigned char *ptr= (unsigned char*) &nr;
1 by brian
clean slate
1577
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
1578
      tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
1579
      tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
1580
#else
1581
      tmp[0]= ptr[7]; tmp[1]=ptr[6]; tmp[2]= ptr[5]; tmp[3]=ptr[4];
1582
      tmp[4]= ptr[3]; tmp[5]=ptr[2]; tmp[6]= ptr[1]; tmp[7]=ptr[0];
1583
#endif
1584
    }
1585
#endif
1586
    if (tmp[0] & 128)				/* Negative */
1587
    {						/* make complement */
438.1.13 by Brian Aker
uint cleanup.
1588
      uint32_t i;
1 by brian
clean slate
1589
      for (i=0 ; i < sizeof(nr); i++)
481 by Brian Aker
Remove all of uchar.
1590
	tmp[i]=tmp[i] ^ (unsigned char) 255;
1 by brian
clean slate
1591
    }
1592
    else
1593
    {					/* Set high and move exponent one up */
438.1.13 by Brian Aker
uint cleanup.
1594
      uint16_t exp_part=(((uint16_t) tmp[0] << 8) | (uint16_t) tmp[1] |
1595
		       (uint16_t) 32768);
1596
      exp_part+= (uint16_t) 1 << (16-1-DBL_EXP_DIG);
481 by Brian Aker
Remove all of uchar.
1597
      tmp[0]= (unsigned char) (exp_part >> 8);
1598
      tmp[1]= (unsigned char) exp_part;
1 by brian
clean slate
1599
    }
1600
  }
1601
}