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