~drizzle-trunk/drizzle/development

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