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