44
41
#include "drizzled/internal/my_sys.h"
45
42
#include "plugin/myisam/myisam.h"
46
43
#include "drizzled/plugin/transactional_storage_engine.h"
47
#include "drizzled/atomics.h"
48
#include "drizzled/global_buffer.h"
51
45
using namespace std;
56
/* Defines used by filesort and uniques */
60
class BufferCompareContext
63
qsort_cmp2 key_compare;
64
void *key_compare_arg;
66
BufferCompareContext() :
75
uint32_t rec_length; /* Length of sorted records */
76
uint32_t sort_length; /* Length of sorted columns */
77
uint32_t ref_length; /* Length of record ref. */
78
uint32_t addon_length; /* Length of added packed fields */
79
uint32_t res_length; /* Length of records in final sorted file/buffer */
80
uint32_t keys; /* Max keys / buffer */
81
ha_rows max_rows,examined_rows;
82
Table *sort_form; /* For quicker make_sortkey */
83
SortField *local_sortorder;
85
sort_addon_field *addon_field; /* Descriptors for companion fields */
86
unsigned char *unique_buff;
89
/* The fields below are used only by Unique class */
91
BufferCompareContext cmp_context;
119
int write_keys(unsigned char * *sort_keys,
121
internal::IO_CACHE *buffer_file,
122
internal::IO_CACHE *tempfile);
124
void make_sortkey(unsigned char *to,
125
unsigned char *ref_pos);
126
void register_used_fields();
127
bool save_index(unsigned char **sort_keys,
129
filesort_info *table_sort);
133
50
/* functions defined in this file */
135
52
static char **make_char_array(char **old_pos, register uint32_t fields,
140
57
unsigned char *buf);
59
static ha_rows find_all_keys(Session *session,
61
optimizer::SqlSelect *select,
62
unsigned char * *sort_keys,
63
internal::IO_CACHE *buffer_file,
64
internal::IO_CACHE *tempfile,
65
internal::IO_CACHE *indexfile);
67
static int write_keys(SORTPARAM *param,
68
unsigned char * *sort_keys,
70
internal::IO_CACHE *buffer_file,
71
internal::IO_CACHE *tempfile);
73
static void make_sortkey(SORTPARAM *param,
75
unsigned char *ref_pos);
76
static void register_used_fields(SORTPARAM *param);
77
static int merge_index(SORTPARAM *param,
78
unsigned char *sort_buffer,
81
internal::IO_CACHE *tempfile,
82
internal::IO_CACHE *outfile);
83
static bool save_index(SORTPARAM *param,
84
unsigned char **sort_keys,
86
filesort_info *table_sort);
142
87
static uint32_t suffix_length(uint32_t string_length);
88
static uint32_t sortlength(Session *session,
91
bool *multi_byte_charset);
92
static sort_addon_field *get_addon_fields(Session *session,
143
96
static void unpack_addon_fields(sort_addon_field *addon_field,
144
97
unsigned char *buff);
146
FileSort::FileSort(Session &arg) :
153
100
Creates a set of pointers that can be used to read the rows
183
131
examined_rows will be set to number of examined rows
186
ha_rows FileSort::run(Table *table, SortField *sortorder, uint32_t s_length,
187
optimizer::SqlSelect *select, ha_rows max_rows,
188
bool sort_positions, ha_rows &examined_rows)
134
ha_rows filesort(Session *session, Table *table, SortField *sortorder, uint32_t s_length,
135
optimizer::SqlSelect *select, ha_rows max_rows,
136
bool sort_positions, ha_rows *examined_rows)
191
uint32_t memavl= 0, min_sort_memory;
139
uint32_t memavl, min_sort_memory;
192
140
uint32_t maxbuffer;
193
size_t allocated_sort_memory= 0;
194
buffpek *buffpek_inst= 0;
141
buffpek *buffpek_inst;
195
142
ha_rows records= HA_POS_ERROR;
196
143
unsigned char **sort_keys= 0;
197
internal::IO_CACHE tempfile;
198
internal::IO_CACHE buffpek_pointers;
199
internal::IO_CACHE *selected_records_file;
200
internal::IO_CACHE *outfile;
144
internal::IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
202
146
bool multi_byte_charset;
205
Don't use table->sort in filesort as it is also used by
206
QuickIndexMergeSelect. Work with a copy and put it back at the end
207
when index_merge select has finished with it.
209
filesort_info table_sort(table->sort);
210
table->sort.io_cache= NULL;
148
filesort_info table_sort;
212
149
TableList *tab= table->pos_in_table_list;
213
150
Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
218
155
Release InnoDB's adaptive hash index latch (if holding) before
221
plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
158
plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
161
Don't use table->sort in filesort as it is also used by
162
QuickIndexMergeSelect. Work with a copy and put it back at the end
163
when index_merge select has finished with it.
165
memcpy(&table_sort, &table->sort, sizeof(filesort_info));
166
table->sort.io_cache= NULL;
224
168
outfile= table_sort.io_cache;
225
assert(tempfile.buffer == 0);
226
assert(buffpek_pointers.buffer == 0);
228
param.sort_length= sortlength(sortorder, s_length, &multi_byte_charset);
169
my_b_clear(&tempfile);
170
my_b_clear(&buffpek_pointers);
173
memset(¶m, 0, sizeof(param));
174
param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
229
175
param.ref_length= table->cursor->ref_length;
176
param.addon_field= 0;
177
param.addon_length= 0;
231
178
if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
234
181
Get the descriptors of all fields whose values are appended
235
182
to sorted fields and get its total length in param.spack_length.
237
param.addon_field= get_addon_fields(table->getFields(),
184
param.addon_field= get_addon_fields(session, table->getFields(),
238
185
param.sort_length,
239
186
¶m.addon_length);
291
236
selected_records_file= 0;
294
if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
239
if (multi_byte_charset &&
240
!(param.tmp_buffer= (char*) malloc(param.sort_length)))
299
memavl= getSession().variables.sortbuff_size;
243
memavl= session->variables.sortbuff_size;
300
244
min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
301
245
while (memavl >= min_sort_memory)
303
247
uint32_t old_memavl;
304
248
uint32_t keys= memavl/(param.rec_length+sizeof(char*));
305
249
param.keys= (uint32_t) min(records+1, (ha_rows)keys);
307
allocated_sort_memory= param.keys * param.rec_length;
308
if (not global_sort_buffer.add(allocated_sort_memory))
310
my_error(ER_OUT_OF_GLOBAL_SORTMEMORY, MYF(ME_ERROR+ME_WAITTANG));
314
250
if ((table_sort.sort_keys=
315
251
(unsigned char **) make_char_array((char **) table_sort.sort_keys,
316
252
param.keys, param.rec_length)))
319
global_sort_buffer.sub(allocated_sort_memory);
320
254
old_memavl= memavl;
321
255
if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
322
256
memavl= min_sort_memory;
327
261
my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
331
if (buffpek_pointers.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
264
if (open_cached_file(&buffpek_pointers,drizzle_tmpdir.c_str(),TEMP_PREFIX,
265
DISK_BUFFER_SIZE, MYF(MY_WME)))
336
268
param.keys--; /* TODO: check why we do this */
337
269
param.sort_form= table;
338
270
param.end=(param.local_sortorder=sortorder)+s_length;
339
if ((records= find_all_keys(¶m,select,sort_keys, &buffpek_pointers,
340
&tempfile, selected_records_file)) == HA_POS_ERROR)
271
if ((records=find_all_keys(session, ¶m,select,sort_keys, &buffpek_pointers,
272
&tempfile, selected_records_file)) ==
344
275
maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
346
277
if (maxbuffer == 0) // The whole set is in memory
348
if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
279
if (save_index(¶m,sort_keys,(uint32_t) records, &table_sort))
359
288
table_sort.buffpek = 0;
361
290
if (!(table_sort.buffpek=
362
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
291
(unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
292
table_sort.buffpek)))
366
294
buffpek_inst= (buffpek *) table_sort.buffpek;
367
295
table_sort.buffpek_len= maxbuffer;
368
buffpek_pointers.close_cached_file();
296
close_cached_file(&buffpek_pointers);
369
297
/* Open cached file if it isn't open */
370
if (! my_b_inited(outfile) && outfile->open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER, MYF(MY_WME)))
375
if (outfile->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
298
if (! my_b_inited(outfile) &&
299
open_cached_file(outfile,drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER,
302
if (reinit_io_cache(outfile,internal::WRITE_CACHE,0L,0,0))
381
306
Use also the space previously used by string pointers in sort_buffer
382
307
for temporary key storage.
384
param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
309
param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
386
311
maxbuffer--; // Offset from 0
387
312
if (merge_many_buff(¶m,(unsigned char*) sort_keys,buffpek_inst,&maxbuffer, &tempfile))
392
if (flush_io_cache(&tempfile) || tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
314
if (flush_io_cache(&tempfile) ||
315
reinit_io_cache(&tempfile,internal::READ_CACHE,0L,0,0))
397
317
if (merge_index(¶m,(unsigned char*) sort_keys,buffpek_inst,maxbuffer,&tempfile, outfile))
403
320
if (records > param.max_rows)
405
records= param.max_rows;
321
records=param.max_rows;
410
if (not subselect || not subselect->is_uncacheable())
325
if (param.tmp_buffer)
326
if (param.tmp_buffer)
327
free(param.tmp_buffer);
328
if (!subselect || !subselect->is_uncacheable())
413
331
table_sort.sort_keys= 0;
415
333
table_sort.buffpek= 0;
416
334
table_sort.buffpek_len= 0;
419
tempfile.close_cached_file();
420
buffpek_pointers.close_cached_file();
336
close_cached_file(&tempfile);
337
close_cached_file(&buffpek_pointers);
422
338
if (my_b_inited(outfile))
424
340
if (flush_io_cache(outfile))
429
internal::my_off_t save_pos= outfile->pos_in_file;
343
internal::my_off_t save_pos=outfile->pos_in_file;
430
344
/* For following reads */
431
if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
345
if (reinit_io_cache(outfile,internal::READ_CACHE,0L,0,0))
435
347
outfile->end_of_file=save_pos;
441
352
my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
446
getSession().status_var.filesort_rows+= (uint32_t) records;
357
session->status_var.filesort_rows+= (uint32_t) records;
448
examined_rows= param.examined_rows;
449
global_sort_buffer.sub(allocated_sort_memory);
450
table->sort= table_sort;
359
*examined_rows= param.examined_rows;
360
memcpy(&table->sort, &table_sort, sizeof(filesort_info));
451
361
DRIZZLE_FILESORT_DONE(error, records);
452
362
return (error ? HA_POS_ERROR : records);
366
void Table::filesort_free_buffers(bool full)
368
if (sort.record_pointers)
370
free((unsigned char*) sort.record_pointers);
371
sort.record_pointers=0;
377
if ((unsigned char*) sort.sort_keys)
378
free((unsigned char*) sort.sort_keys);
383
if ((unsigned char*) sort.buffpek)
384
free((unsigned char*) sort.buffpek);
391
free((char *) sort.addon_buf);
392
free((char *) sort.addon_field);
455
398
/** Make a array of string pointers. */
457
400
static char **make_char_array(char **old_pos, register uint32_t fields,
532
475
HA_POS_ERROR on error.
535
ha_rows FileSort::find_all_keys(SortParam *param,
536
optimizer::SqlSelect *select,
537
unsigned char **sort_keys,
538
internal::IO_CACHE *buffpek_pointers,
539
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
478
static ha_rows find_all_keys(Session *session,
480
optimizer::SqlSelect *select,
481
unsigned char **sort_keys,
482
internal::IO_CACHE *buffpek_pointers,
483
internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
541
485
int error,flag,quick_select;
542
486
uint32_t idx,indexpos,ref_length;
543
487
unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
544
488
internal::my_off_t record;
545
489
Table *sort_form;
546
volatile Session::killed_state_t *killed= getSession().getKilledPtr();
490
volatile Session::killed_state *killed= &session->killed;
548
492
boost::dynamic_bitset<> *save_read_set= NULL;
549
493
boost::dynamic_bitset<> *save_write_set= NULL;
724
int SortParam::write_keys(register unsigned char **sort_keys, uint32_t count,
725
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
662
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
663
internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
665
size_t sort_length, rec_length;
669
sort_length= param->sort_length;
670
rec_length= param->rec_length;
729
671
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
730
672
if (!my_b_inited(tempfile) &&
731
tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
673
open_cached_file(tempfile, drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE,
820
762
Item *item=sort_field->item;
821
763
maybe_null= item->maybe_null;
823
764
switch (sort_field->result_type) {
824
765
case STRING_RESULT:
826
const CHARSET_INFO * const cs=item->collation.collation;
827
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
829
uint32_t sort_field_length;
767
const CHARSET_INFO * const cs=item->collation.collation;
768
char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
770
uint32_t sort_field_length;
774
/* All item->str() to use some extra byte for end null.. */
775
String tmp((char*) to,sort_field->length+4,cs);
776
String *res= item->str_result(&tmp);
833
/* All item->str() to use some extra byte for end null.. */
834
String tmp((char*) to,sort_field->length+4,cs);
835
String *res= item->str_result(&tmp);
839
memset(to-1, 0, sort_field->length+1);
843
This should only happen during extreme conditions if we run out
844
of memory or have an item marked not null when it can be null.
845
This code is here mainly to avoid a hard crash in this case.
848
memset(to, 0, sort_field->length); // Avoid crash
852
length= res->length();
853
sort_field_length= sort_field->length - sort_field->suffix_length;
854
diff=(int) (sort_field_length - length);
858
length= sort_field_length;
860
if (sort_field->suffix_length)
862
/* Store length last in result_string */
863
store_length(to + sort_field_length, length,
864
sort_field->suffix_length);
866
if (sort_field->need_strxnfrm)
868
char *from=(char*) res->ptr();
870
if ((unsigned char*) from == to)
872
set_if_smaller(length,sort_field->length);
873
memcpy(tmp_buffer,from,length);
876
tmp_length= my_strnxfrm(cs,to,sort_field->length,
877
(unsigned char*) from, length);
878
assert(tmp_length == sort_field->length);
780
memset(to-1, 0, sort_field->length+1);
882
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
883
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
784
This should only happen during extreme conditions if we run out
785
of memory or have an item marked not null when it can be null.
786
This code is here mainly to avoid a hard crash in this case.
789
memset(to, 0, sort_field->length); // Avoid crash
793
length= res->length();
794
sort_field_length= sort_field->length - sort_field->suffix_length;
795
diff=(int) (sort_field_length - length);
799
length= sort_field_length;
801
if (sort_field->suffix_length)
803
/* Store length last in result_string */
804
store_length(to + sort_field_length, length,
805
sort_field->suffix_length);
807
if (sort_field->need_strxnfrm)
809
char *from=(char*) res->ptr();
811
if ((unsigned char*) from == to)
813
set_if_smaller(length,sort_field->length);
814
memcpy(param->tmp_buffer,from,length);
815
from=param->tmp_buffer;
817
tmp_length= my_strnxfrm(cs,to,sort_field->length,
818
(unsigned char*) from, length);
819
assert(tmp_length == sort_field->length);
823
my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
824
cs->cset->fill(cs, (char *)to+length,diff,fill_char);
889
830
int64_t value= item->val_int_result();
893
834
if (item->null_value)
904
to[7]= (unsigned char) value;
905
to[6]= (unsigned char) (value >> 8);
906
to[5]= (unsigned char) (value >> 16);
907
to[4]= (unsigned char) (value >> 24);
908
to[3]= (unsigned char) (value >> 32);
909
to[2]= (unsigned char) (value >> 40);
910
to[1]= (unsigned char) (value >> 48);
845
to[7]= (unsigned char) value;
846
to[6]= (unsigned char) (value >> 8);
847
to[5]= (unsigned char) (value >> 16);
848
to[4]= (unsigned char) (value >> 24);
849
to[3]= (unsigned char) (value >> 32);
850
to[2]= (unsigned char) (value >> 40);
851
to[1]= (unsigned char) (value >> 48);
911
852
if (item->unsigned_flag) /* Fix sign */
912
853
to[0]= (unsigned char) (value >> 56);
914
855
to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
917
858
case DECIMAL_RESULT:
919
type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
860
my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
922
863
if (item->null_value)
1062
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
1001
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
1002
filesort_info *table_sort)
1004
uint32_t offset,res_length;
1065
1005
unsigned char *to;
1067
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1068
offset= rec_length - res_length;
1070
if ((ha_rows) count > max_rows)
1071
count=(uint32_t) max_rows;
1073
if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
1076
for (unsigned char **end_ptr= sort_keys+count ; sort_keys != end_ptr ; sort_keys++)
1007
internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
1008
res_length= param->res_length;
1009
offset= param->rec_length-res_length;
1010
if ((ha_rows) count > param->max_rows)
1011
count=(uint32_t) param->max_rows;
1012
if (!(to= table_sort->record_pointers=
1013
(unsigned char*) malloc(res_length*count)))
1015
for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1078
1017
memcpy(to, *sort_keys+offset, res_length);
1079
1018
to+= res_length;
1086
1024
/** Merge buffers to make < MERGEBUFF2 buffers. */
1088
int FileSort::merge_many_buff(SortParam *param, unsigned char *sort_buffer,
1089
buffpek *buffpek_inst, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1026
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
1027
buffpek *buffpek_inst, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
1091
1029
internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1092
1030
buffpek *lastbuff;
1220
int FileSort::merge_buffers(SortParam *param, internal::IO_CACHE *from_file,
1221
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1222
buffpek *lastbuff, buffpek *Fb, buffpek *Tb,
1155
int merge_buffers(SORTPARAM *param, internal::IO_CACHE *from_file,
1156
internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1157
buffpek *lastbuff, buffpek *Fb, buffpek *Tb,
1226
1161
uint32_t rec_length,res_length,offset;
1431
1366
/* Do a merge to output-file (save only positions) */
1433
int FileSort::merge_index(SortParam *param, unsigned char *sort_buffer,
1434
buffpek *buffpek_inst, uint32_t maxbuffer,
1435
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1368
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
1369
buffpek *buffpek_inst, uint32_t maxbuffer,
1370
internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
1437
1372
if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1438
1373
buffpek_inst+maxbuffer,1))
1442
1376
} /* merge_index */
1502
1439
sortorder->result_type= sortorder->item->result_type();
1503
1440
if (sortorder->item->result_as_int64_t())
1504
1441
sortorder->result_type= INT_RESULT;
1506
1442
switch (sortorder->result_type) {
1507
1443
case STRING_RESULT:
1508
sortorder->length=sortorder->item->max_length;
1444
sortorder->length=sortorder->item->max_length;
1509
1445
set_if_smaller(sortorder->length,
1510
getSession().variables.max_sort_length);
1511
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1446
session->variables.max_sort_length);
1447
if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1513
1449
sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1514
sortorder->need_strxnfrm= 1;
1515
*multi_byte_charset= 1;
1450
sortorder->need_strxnfrm= 1;
1451
*multi_byte_charset= 1;
1517
1453
else if (cs == &my_charset_bin)
1519
1455
/* Store length last to be able to sort blob/varbinary */
1520
1456
sortorder->suffix_length= suffix_length(sortorder->length);
1521
1457
sortorder->length+= sortorder->suffix_length;
1524
1460
case INT_RESULT:
1525
sortorder->length=8; // Size of intern int64_t
1461
sortorder->length=8; // Size of intern int64_t
1527
1463
case DECIMAL_RESULT:
1528
1464
sortorder->length=
1529
class_decimal_get_binary_size(sortorder->item->max_length -
1465
my_decimal_get_binary_size(sortorder->item->max_length -
1530
1466
(sortorder->item->decimals ? 1 : 0),
1531
1467
sortorder->item->decimals);
1533
1469
case REAL_RESULT:
1534
sortorder->length=sizeof(double);
1470
sortorder->length=sizeof(double);
1536
1472
case ROW_RESULT:
1537
// This case should never be choosen
1474
// This case should never be choosen
1541
1478
if (sortorder->item->maybe_null)
1542
length++; // Place for NULL marker
1479
length++; // Place for NULL marker
1544
set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1481
set_if_smaller(sortorder->length,
1482
(size_t)session->variables.max_sort_length);
1545
1483
length+=sortorder->length;
1547
1485
sortorder->field= (Field*) 0; // end marker