24
24
#include <drizzled/server_includes.h>
25
#include <drizzled/sql_sort.h>
26
#include <drizzled/error.h>
27
#include <drizzled/probes.h>
28
#include <drizzled/session.h>
29
#include <drizzled/table.h>
30
#include <drizzled/table_list.h>
37
/* functions defined in this file */
26
#include <drizzled/drizzled_error_messages.h>
28
/* functions defined in this file */
39
30
static char **make_char_array(char **old_pos, register uint32_t fields,
31
uint32_t length, myf my_flag);
41
32
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
42
33
unsigned char *buf);
43
34
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
52
43
uint32_t maxbuffer,IO_CACHE *tempfile,
53
44
IO_CACHE *outfile);
54
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
45
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
55
46
filesort_info_st *table_sort);
56
47
static uint32_t suffix_length(uint32_t string_length);
57
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
48
static uint32_t sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
58
49
bool *multi_byte_charset);
59
static SORT_ADDON_FIELD *get_addon_fields(Session *session, Field **ptabfield,
50
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
60
51
uint32_t sortlength, uint32_t *plength);
61
52
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
62
53
unsigned char *buff);
96
87
examined_rows will be set to number of examined rows
99
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
90
ha_rows filesort(THD *thd, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
100
91
SQL_SELECT *select, ha_rows max_rows,
101
92
bool sort_positions, ha_rows *examined_rows)
107
98
ha_rows records= HA_POS_ERROR;
108
99
unsigned char **sort_keys= 0;
109
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
100
IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
111
102
bool multi_byte_charset;
114
105
TableList *tab= table->pos_in_table_list;
115
106
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
117
DRIZZLE_FILESORT_START(table->s->db.str, table->s->table_name.str);
108
DRIZZLE_FILESORT_START();
120
111
Release InnoDB's adaptive hash index latch (if holding) before
123
ha_release_temporary_latches(session);
114
ha_release_temporary_latches(thd);
126
Don't use table->sort in filesort as it is also used by
127
QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
117
Don't use table->sort in filesort as it is also used by
118
QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
128
119
when index_merge select has finished with it.
130
121
memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
131
122
table->sort.io_cache= NULL;
133
124
outfile= table_sort.io_cache;
134
125
my_b_clear(&tempfile);
135
126
my_b_clear(&buffpek_pointers);
138
129
memset(¶m, 0, sizeof(param));
139
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
130
param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset);
140
131
param.ref_length= table->file->ref_length;
141
132
param.addon_field= 0;
142
133
param.addon_length= 0;
143
134
if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
146
Get the descriptors of all fields whose values are appended
137
Get the descriptors of all fields whose values are appended
147
138
to sorted fields and get its total length in param.spack_length.
149
param.addon_field= get_addon_fields(session, table->field,
140
param.addon_field= get_addon_fields(thd, table->field,
150
141
param.sort_length,
151
142
¶m.addon_length);
158
149
if (param.addon_field)
160
151
param.res_length= param.addon_length;
161
if (!(table_sort.addon_buf= (unsigned char *) malloc(param.addon_length)))
152
if (!(table_sort.addon_buf= (unsigned char *) my_malloc(param.addon_length,
166
158
param.res_length= param.ref_length;
168
The reference to the record is considered
160
The reference to the record is considered
169
161
as an additional sorted field
171
163
param.sort_length+= param.ref_length;
176
168
if (select && select->quick)
178
status_var_increment(session->status_var.filesort_range_count);
170
status_var_increment(thd->status_var.filesort_range_count);
182
status_var_increment(session->status_var.filesort_scan_count);
174
status_var_increment(thd->status_var.filesort_scan_count);
184
176
#ifdef CAN_TRUST_RANGE
185
177
if (select && select->quick && select->quick->records > 0L)
187
records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
188
table->file->stats.records)+EXTRA_RECORDS;
179
records=cmin((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
180
table->file->stats.records)+EXTRA_RECORDS;
189
181
selected_records_file=0;
194
186
records= table->file->estimate_rows_upper_bound();
196
If number of records is not known, use as much of sort buffer
188
If number of records is not known, use as much of sort buffer
199
191
if (records == HA_POS_ERROR)
200
192
records--; // we use 'records+1' below.
204
196
if (multi_byte_charset &&
205
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
197
!(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
208
memavl= session->variables.sortbuff_size;
209
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
200
memavl= thd->variables.sortbuff_size;
201
min_sort_memory= cmax((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
210
202
while (memavl >= min_sort_memory)
212
204
uint32_t old_memavl;
213
205
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
214
param.keys= (uint32_t) min(records+1, (ha_rows)keys);
206
param.keys=(uint32_t) cmin(records+1, keys);
215
207
if ((table_sort.sort_keys=
216
208
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
217
param.keys, param.rec_length)))
209
param.keys, param.rec_length, MYF(0))))
220
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
212
if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
221
213
memavl= min_sort_memory;
223
215
sort_keys= table_sort.sort_keys;
226
218
my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
229
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
221
if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
230
222
DISK_BUFFER_SIZE, MYF(MY_WME)))
261
253
close_cached_file(&buffpek_pointers);
262
254
/* Open cached file if it isn't open */
263
255
if (! my_b_inited(outfile) &&
264
open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
256
open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
267
259
if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
320
312
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
321
313
MYF(ME_ERROR+ME_WAITTANG));
323
statistic_add(session->status_var.filesort_rows,
315
statistic_add(thd->status_var.filesort_rows,
324
316
(uint32_t) records, &LOCK_status);
325
317
*examined_rows= param.examined_rows;
326
318
memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
327
DRIZZLE_FILESORT_DONE(error, records);
328
return (error ? HA_POS_ERROR : records);
319
DRIZZLE_FILESORT_END();
320
return(error ? HA_POS_ERROR : records);
332
void Table::filesort_free_buffers(bool full)
324
void filesort_free_buffers(Table *table, bool full)
334
if (sort.record_pointers)
326
if (table->sort.record_pointers)
336
free((unsigned char*) sort.record_pointers);
337
sort.record_pointers=0;
328
free((unsigned char*) table->sort.record_pointers);
329
table->sort.record_pointers=0;
333
if (table->sort.sort_keys )
343
if ((unsigned char*) sort.sort_keys)
344
free((unsigned char*) sort.sort_keys);
335
if ((unsigned char*) table->sort.sort_keys)
336
free((unsigned char*) table->sort.sort_keys);
337
table->sort.sort_keys= 0;
339
if (table->sort.buffpek)
349
if ((unsigned char*) sort.buffpek)
350
free((unsigned char*) sort.buffpek);
341
if ((unsigned char*) table->sort.buffpek)
342
free((unsigned char*) table->sort.buffpek);
343
table->sort.buffpek= 0;
344
table->sort.buffpek_len= 0;
347
if (table->sort.addon_buf)
357
free((char *) sort.addon_buf);
358
free((char *) sort.addon_field);
349
free((char *) table->sort.addon_buf);
350
free((char *) table->sort.addon_field);
351
table->sort.addon_buf=0;
352
table->sort.addon_field=0;
364
356
/** Make a array of string pointers. */
366
358
static char **make_char_array(char **old_pos, register uint32_t fields,
359
uint32_t length, myf my_flag)
369
361
register char **pos;
373
(old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
365
(old_pos= (char**) my_malloc((uint32_t) fields*(length+sizeof(char*)),
375
368
pos=old_pos; char_pos=((char*) (pos+fields)) -length;
376
369
while (fields--) *(pos++) = (char_pos+= length);
390
383
if (count > UINT_MAX/sizeof(BUFFPEK))
391
384
return 0; /* sizeof(BUFFPEK)*count will overflow */
393
tmp= (unsigned char *)malloc(length);
386
tmp= (unsigned char *)my_malloc(length, MYF(MY_WME));
396
389
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
451
444
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
453
446
Table *sort_form;
454
Session *session= current_session;
455
volatile Session::killed_state *killed= &session->killed;
447
THD *thd= current_thd;
448
volatile THD::killed_state *killed= &thd->killed;
457
MyBitmap *save_read_set, *save_write_set;
450
MY_BITMAP *save_read_set, *save_write_set;
460
453
error=quick_select=0;
490
483
save_read_set= sort_form->read_set;
491
484
save_write_set= sort_form->write_set;
492
485
/* Set up temporary column read map for columns used by sort */
493
sort_form->tmp_set.clearAll();
486
bitmap_clear_all(&sort_form->tmp_set);
494
487
/* Temporary set for register_used_fields and register_field_in_read_map */
495
488
sort_form->read_set= &sort_form->tmp_set;
496
489
register_used_fields(param);
580
572
file->ha_rnd_end();
583
if (session->is_error())
584
576
return(HA_POS_ERROR);
586
578
/* Signal we should use orignal column read and write maps */
587
579
sort_form->column_bitmaps_set(save_read_set, save_write_set);
589
581
if (error != HA_ERR_END_OF_FILE)
591
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
592
return(HA_POS_ERROR);
583
file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); /* purecov: inspected */
584
return(HA_POS_ERROR); /* purecov: inspected */
594
586
if (indexpos && idx &&
595
587
write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
596
return(HA_POS_ERROR);
588
return(HA_POS_ERROR); /* purecov: inspected */
597
589
return(my_b_inited(tempfile) ?
598
590
(ha_rows) (my_b_tell(tempfile)/param->rec_length) :
634
626
rec_length= param->rec_length;
635
627
my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
636
628
if (!my_b_inited(tempfile) &&
637
open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
629
open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
631
goto err; /* purecov: inspected */
640
632
/* check we won't have more buffpeks than we can possibly keep in memory */
641
633
if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
643
635
buffpek.file_pos= my_b_tell(tempfile);
644
636
if ((ha_rows) count > param->max_rows)
645
count=(uint32_t) param->max_rows;
637
count=(uint32_t) param->max_rows; /* purecov: inspected */
646
638
buffpek.count=(ha_rows) count;
647
639
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
648
640
if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
807
802
to[0]= (unsigned char) (value >> 56);
809
804
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
806
to[3]= (unsigned char) value;
807
to[2]= (unsigned char) (value >> 8);
808
to[1]= (unsigned char) (value >> 16);
809
if (item->unsigned_flag) /* Fix sign */
810
to[0]= (unsigned char) (value >> 24);
812
to[0]= (unsigned char) (value >> 24) ^ 128; /* Reverse signbit */
812
816
case DECIMAL_RESULT:
955
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
960
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
956
961
filesort_info_st *table_sort)
958
963
uint32_t offset,res_length;
963
968
offset= param->rec_length-res_length;
964
969
if ((ha_rows) count > param->max_rows)
965
970
count=(uint32_t) param->max_rows;
966
if (!(to= table_sort->record_pointers=
967
(unsigned char*) malloc(res_length*count)))
971
if (!(to= table_sort->record_pointers=
972
(unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
973
return(1); /* purecov: inspected */
969
974
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
971
976
memcpy(to, *sort_keys+offset, res_length);
985
990
BUFFPEK *lastbuff;
987
992
if (*maxbuffer < MERGEBUFF2)
993
return(0); /* purecov: inspected */
989
994
if (flush_io_cache(t_file) ||
990
open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
995
open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
997
return(1); /* purecov: inspected */
994
999
from_file= t_file ; to_file= &t_file2;
995
1000
while (*maxbuffer >= MERGEBUFF2)
1008
1013
if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1009
1014
buffpek+i,buffpek+ *maxbuffer,0))
1015
break; /* purecov: inspected */
1011
1016
if (flush_io_cache(to_file))
1017
break; /* purecov: inspected */
1013
1018
temp=from_file; from_file=to_file; to_file=temp;
1014
1019
setup_io_cache(from_file);
1015
1020
setup_io_cache(to_file);
1037
1042
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1038
uint32_t rec_length)
1043
uint32_t rec_length)
1040
1045
register uint32_t count;
1041
1046
uint32_t length;
1043
if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1048
if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1045
1050
if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1046
return((uint32_t) -1);
1048
buffpek->key= buffpek->base;
1051
return((uint32_t) -1); /* purecov: inspected */
1052
buffpek->key=buffpek->base;
1049
1053
buffpek->file_pos+= length; /* New filepos */
1050
buffpek->count-= count;
1054
buffpek->count-= count;
1051
1055
buffpek->mem_count= count;
1053
1057
return (count*rec_length);
1054
1058
} /* read_to_buffer */
1057
class compare_functor
1062
Put all room used by freed buffer to use in adjacent buffer.
1064
Note, that we can't simply distribute memory evenly between all buffers,
1065
because new areas must not overlap with old ones.
1067
@param[in] queue list of non-empty buffers, without freed buffer
1068
@param[in] reuse empty buffer
1069
@param[in] key_length key length
1072
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint32_t key_length)
1059
qsort2_cmp key_compare;
1060
void *key_compare_arg;
1062
compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
1063
: key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
1064
inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
1074
unsigned char *reuse_end= reuse->base + reuse->max_keys * key_length;
1075
for (uint32_t i= 0; i < queue->elements; ++i)
1066
int val= key_compare(key_compare_arg,
1077
BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1078
if (bp->base + bp->max_keys * key_length == reuse->base)
1080
bp->max_keys+= reuse->max_keys;
1083
else if (bp->base == reuse_end)
1085
bp->base= reuse->base;
1086
bp->max_keys+= reuse->max_keys;
1101
1122
my_off_t to_start_filepos;
1102
1123
unsigned char *strpos;
1103
1124
BUFFPEK *buffpek;
1104
1126
qsort2_cmp cmp;
1105
1127
void *first_cmp_arg;
1106
volatile Session::killed_state *killed= ¤t_session->killed;
1107
Session::killed_state not_killable;
1128
volatile THD::killed_state *killed= ¤t_thd->killed;
1129
THD::killed_state not_killable;
1109
status_var_increment(current_session->status_var.filesort_merge_passes);
1131
status_var_increment(current_thd->status_var.filesort_merge_passes);
1110
1132
if (param->not_killable)
1112
1134
killed= ¬_killable;
1113
not_killable= Session::NOT_KILLED;
1135
not_killable= THD::NOT_KILLED;
1136
1158
cmp= get_ptr_compare(sort_length);
1137
1159
first_cmp_arg= (void*) &sort_length;
1139
priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor >
1140
queue(compare_functor(cmp, first_cmp_arg));
1161
if (init_queue(&queue, (uint32_t) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1162
(queue_compare) cmp, first_cmp_arg))
1163
return(1); /* purecov: inspected */
1141
1164
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1143
1166
buffpek->base= strpos;
1145
1168
strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1147
1170
if (error == -1)
1171
goto err; /* purecov: inspected */
1149
1172
buffpek->max_keys= buffpek->mem_count; // If less data in buffers than expected
1150
queue.push(buffpek);
1173
queue_insert(&queue, (unsigned char*) buffpek);
1153
1176
if (param->unique_buff)
1156
1179
Called by Unique::get()
1157
1180
Copy the first argument to param->unique_buff for unique removal.
1158
1181
Store it also in 'to_file'.
1160
1183
This is safe as we know that there is always more than one element
1161
1184
in each block to merge (This is guaranteed by the Unique:: algorithm
1163
buffpek= queue.top();
1186
buffpek= (BUFFPEK*) queue_top(&queue);
1164
1187
memcpy(param->unique_buff, buffpek->key, rec_length);
1165
1188
if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1190
error=1; goto err; /* purecov: inspected */
1169
1192
buffpek->key+= rec_length;
1170
1193
buffpek->mem_count--;
1171
1194
if (!--max_rows)
1196
error= 0; /* purecov: inspected */
1197
goto end; /* purecov: inspected */
1176
/* Top element has been used */
1178
queue.push(buffpek);
1199
queue_replaced(&queue); // Top element has been used
1181
1202
cmp= 0; // Not unique
1183
while (queue.size() > 1)
1204
while (queue.elements > 1)
1208
error= 1; goto err; /* purecov: inspected */
1191
buffpek= queue.top();
1212
buffpek= (BUFFPEK*) queue_top(&queue);
1192
1213
if (cmp) // Remove duplicates
1194
1215
if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1201
1222
if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1224
error=1; goto err; /* purecov: inspected */
1208
1229
if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1231
error=1; goto err; /* purecov: inspected */
1213
1234
if (!--max_rows)
1236
error= 0; /* purecov: inspected */
1237
goto end; /* purecov: inspected */
1219
1240
skip_duplicate:
1223
1244
if (!(error= (int) read_to_buffer(from_file,buffpek,
1247
queue_remove(&queue,0);
1248
reuse_freed_buff(&queue, buffpek, rec_length);
1227
1249
break; /* One buffer have been removed */
1229
1251
else if (error == -1)
1252
goto err; /* purecov: inspected */
1232
/* Top element has been replaced */
1234
queue.push(buffpek);
1254
queue_replaced(&queue); /* Top element has been replaced */
1237
buffpek= queue.top();
1257
buffpek= (BUFFPEK*) queue_top(&queue);
1238
1258
buffpek->base= sort_buffer;
1239
1259
buffpek->max_keys= param->keys;
1323
1344
Calculate length of sort key.
1325
@param session Thread handler
1346
@param thd Thread handler
1326
1347
@param sortorder Order of items to sort
1327
1348
@param s_length Number of items to sort
1328
1349
@param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1340
1361
static uint32_t
1341
sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
1362
sortlength(THD *thd, SORT_FIELD *sortorder, uint32_t s_length,
1342
1363
bool *multi_byte_charset)
1344
1365
register uint32_t length;
1372
1393
switch (sortorder->result_type) {
1373
1394
case STRING_RESULT:
1374
1395
sortorder->length=sortorder->item->max_length;
1375
set_if_smaller(sortorder->length,
1376
session->variables.max_sort_length);
1396
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1377
1397
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1379
1399
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1380
1400
sortorder->need_strxnfrm= 1;
1381
1401
*multi_byte_charset= 1;
1408
1432
if (sortorder->item->maybe_null)
1409
1433
length++; // Place for NULL marker
1411
set_if_smaller(sortorder->length,
1412
(size_t)session->variables.max_sort_length);
1435
set_if_smaller(sortorder->length, thd->variables.max_sort_length);
1413
1436
length+=sortorder->length;
1415
1438
sortorder->field= (Field*) 0; // end marker
1424
1447
The function first finds out what fields are used in the result set.
1425
1448
Then it calculates the length of the buffer to store the values of
1426
these fields together with the value of sort values.
1449
these fields together with the value of sort values.
1427
1450
If the calculated length is not greater than max_length_for_sort_data
1428
1451
the function allocates memory for an array of descriptors containing
1429
1452
layouts for the values of the non-sorted fields in the buffer and
1432
@param session Current thread
1455
@param thd Current thread
1433
1456
@param ptabfield Array of references to the table fields
1434
1457
@param sortlength Total length of sorted fields
1435
1458
@param[out] plength Total length of appended fields
1460
1484
Note for future refinement:
1461
1485
This this a too strong condition.
1462
1486
Actually we need only the fields referred in the
1463
result set. And for some of them it makes sense to use
1487
result set. And for some of them it makes sense to use
1464
1488
the values directly from sorted fields.
1468
1492
for (pfield= ptabfield; (field= *pfield) ; pfield++)
1470
if (!(field->isReadSet()))
1494
if (!bitmap_is_set(read_set, field->field_index))
1472
1496
if (field->flags & BLOB_FLAG)
1475
1499
if (field->maybe_null())
1481
1505
length+= (null_fields+7)/8;
1483
if (length+sortlength > session->variables.max_length_for_sort_data ||
1484
!(addonf= (SORT_ADDON_FIELD *) malloc(sizeof(SORT_ADDON_FIELD)*
1507
if (length+sortlength > thd->variables.max_length_for_sort_data ||
1508
!(addonf= (SORT_ADDON_FIELD *) my_malloc(sizeof(SORT_ADDON_FIELD)*
1509
(fields+1), MYF(MY_WME))))
1488
1512
*plength= length;