~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/varstring.cc

  • Committer: Brian Aker
  • Date: 2009-07-11 19:23:04 UTC
  • mfrom: (1089.1.14 merge)
  • Revision ID: brian@gaz-20090711192304-ootijyl5yf9jq9kd
Merge Brian

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
1
/* - mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
4
 *  Copyright (C) 2008 MySQL
18
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#ifdef USE_PRAGMA_IMPLEMENTATION
22
 
#pragma implementation                          // gcc: Class implementation
23
 
#endif
24
21
 
25
22
#include <drizzled/server_includes.h>
26
23
#include <drizzled/field/varstring.h>
 
24
#include <drizzled/table.h>
 
25
#include <drizzled/session.h>
 
26
 
 
27
#include <string>
 
28
 
 
29
using namespace std;
27
30
 
28
31
/****************************************************************************
29
32
  VARCHAR type
41
44
  is 2.
42
45
****************************************************************************/
43
46
 
44
 
const uint Field_varstring::MAX_SIZE= UINT16_MAX;
 
47
const uint32_t Field_varstring::MAX_SIZE= UINT16_MAX;
 
48
 
 
49
Field_varstring::Field_varstring(unsigned char *ptr_arg,
 
50
                                 uint32_t len_arg, uint32_t length_bytes_arg,
 
51
                                 unsigned char *null_ptr_arg,
 
52
                                 unsigned char null_bit_arg,
 
53
                                 enum utype unireg_check_arg,
 
54
                                 const char *field_name_arg,
 
55
                                 TableShare *share,
 
56
                                 const CHARSET_INFO * const cs)
 
57
  :Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 
58
                 unireg_check_arg, field_name_arg, cs),
 
59
   length_bytes(length_bytes_arg)
 
60
{
 
61
  share->varchar_fields++;
 
62
}
 
63
 
 
64
Field_varstring::Field_varstring(uint32_t len_arg,bool maybe_null_arg,
 
65
                                 const char *field_name_arg,
 
66
                                 TableShare *share,
 
67
                                 const CHARSET_INFO * const cs)
 
68
  :Field_str((unsigned char*) 0,len_arg,
 
69
                 maybe_null_arg ? (unsigned char*) "": 0, 0,
 
70
                 NONE, field_name_arg, cs),
 
71
   length_bytes(len_arg < 256 ? 1 :2)
 
72
{
 
73
  share->varchar_fields++;
 
74
}
 
75
 
45
76
 
46
77
/**
47
78
   Save the field metadata for varstring fields.
54
85
 
55
86
   @returns number of bytes written to metadata_ptr
56
87
*/
57
 
int Field_varstring::do_save_field_metadata(uchar *metadata_ptr)
 
88
int Field_varstring::do_save_field_metadata(unsigned char *metadata_ptr)
58
89
{
59
 
  char *ptr= (char *)metadata_ptr;
60
90
  assert(field_length <= 65535);
61
 
  int2store(ptr, field_length);
 
91
  int2store(metadata_ptr, field_length);
62
92
  return 2;
63
93
}
64
94
 
65
 
int Field_varstring::store(const char *from,uint length, const CHARSET_INFO * const cs)
 
95
int Field_varstring::store(const char *from,uint32_t length, const CHARSET_INFO * const cs)
66
96
{
67
 
  uint copy_length;
 
97
  uint32_t copy_length;
68
98
  const char *well_formed_error_pos;
69
99
  const char *cannot_convert_error_pos;
70
100
  const char *from_end_pos;
71
101
 
 
102
  ASSERT_COLUMN_MARKED_FOR_WRITE;
 
103
 
72
104
  copy_length= well_formed_copy_nchars(field_charset,
73
105
                                       (char*) ptr + length_bytes,
74
106
                                       field_length,
79
111
                                       &from_end_pos);
80
112
 
81
113
  if (length_bytes == 1)
82
 
    *ptr= (uchar) copy_length;
 
114
    *ptr= (unsigned char) copy_length;
83
115
  else
84
116
    int2store(ptr, copy_length);
85
117
 
94
126
int Field_varstring::store(int64_t nr, bool unsigned_val)
95
127
{
96
128
  char buff[64];
97
 
  uint  length;
98
 
  length= (uint) (field_charset->cset->int64_t10_to_str)(field_charset,
 
129
  uint32_t  length;
 
130
  length= (uint32_t) (field_charset->cset->int64_t10_to_str)(field_charset,
99
131
                                                          buff,
100
132
                                                          sizeof(buff),
101
133
                                                          (unsigned_val ? 10:
109
141
{
110
142
  int not_used;
111
143
  char *end_not_used;
112
 
  uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
 
144
 
 
145
  ASSERT_COLUMN_MARKED_FOR_READ;
 
146
 
 
147
  uint32_t length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
 
148
 
113
149
  return my_strntod(field_charset, (char*) ptr+length_bytes, length,
114
150
                    &end_not_used, &not_used);
115
151
}
119
155
{
120
156
  int not_used;
121
157
  char *end_not_used;
122
 
  uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
 
158
  uint32_t length;
 
159
 
 
160
  ASSERT_COLUMN_MARKED_FOR_READ;
 
161
 
 
162
  length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
 
163
 
123
164
  return my_strntoll(field_charset, (char*) ptr+length_bytes, length, 10,
124
165
                     &end_not_used, &not_used);
125
166
}
126
167
 
127
 
String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
 
168
String *Field_varstring::val_str(String *,
128
169
                                 String *val_ptr)
129
170
{
130
 
  uint length=  length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
 
171
  uint32_t length=  length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
 
172
 
 
173
  ASSERT_COLUMN_MARKED_FOR_READ;
 
174
 
131
175
  val_ptr->set((const char*) ptr+length_bytes, length, field_charset);
 
176
 
132
177
  return val_ptr;
133
178
}
134
179
 
135
180
 
136
181
my_decimal *Field_varstring::val_decimal(my_decimal *decimal_value)
137
182
{
138
 
  uint length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
 
183
  uint32_t length;
 
184
 
 
185
  ASSERT_COLUMN_MARKED_FOR_READ;
 
186
 
 
187
  length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
 
188
 
139
189
  str2my_decimal(E_DEC_FATAL_ERROR, (char*) ptr+length_bytes, length,
140
190
                 charset(), decimal_value);
141
191
  return decimal_value;
142
192
}
143
193
 
144
194
 
145
 
int Field_varstring::cmp_max(const uchar *a_ptr, const uchar *b_ptr,
146
 
                             uint max_len)
 
195
int Field_varstring::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
 
196
                             uint32_t max_len)
147
197
{
148
 
  uint a_length, b_length;
 
198
  uint32_t a_length, b_length;
149
199
  int diff;
150
200
 
151
201
  if (length_bytes == 1)
152
202
  {
153
 
    a_length= (uint) *a_ptr;
154
 
    b_length= (uint) *b_ptr;
 
203
    a_length= (uint32_t) *a_ptr;
 
204
    b_length= (uint32_t) *b_ptr;
155
205
  }
156
206
  else
157
207
  {
176
226
    varstring and blob keys are ALWAYS stored with a 2 byte length prefix
177
227
*/
178
228
 
179
 
int Field_varstring::key_cmp(const uchar *key_ptr, uint max_key_length)
 
229
int Field_varstring::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
180
230
{
181
 
  uint length=  length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
182
 
  uint local_char_length= max_key_length / field_charset->mbmaxlen;
 
231
  uint32_t length=  length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
 
232
  uint32_t local_char_length= max_key_length / field_charset->mbmaxlen;
183
233
 
184
234
  local_char_length= my_charpos(field_charset, ptr + length_bytes,
185
235
                          ptr + length_bytes + length, local_char_length);
186
236
  set_if_smaller(length, local_char_length);
187
 
  return field_charset->coll->strnncollsp(field_charset, 
 
237
  return field_charset->coll->strnncollsp(field_charset,
188
238
                                          ptr + length_bytes,
189
239
                                          length,
190
240
                                          key_ptr+
201
251
    (keys are created and compared in key.cc)
202
252
*/
203
253
 
204
 
int Field_varstring::key_cmp(const uchar *a,const uchar *b)
 
254
int Field_varstring::key_cmp(const unsigned char *a,const unsigned char *b)
205
255
{
206
256
  return field_charset->coll->strnncollsp(field_charset,
207
257
                                          a + HA_KEY_BLOB_LENGTH,
212
262
}
213
263
 
214
264
 
215
 
void Field_varstring::sort_string(uchar *to,uint length)
 
265
void Field_varstring::sort_string(unsigned char *to,uint32_t length)
216
266
{
217
 
  uint tot_length=  length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
 
267
  uint32_t tot_length=  length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
218
268
 
219
269
  if (field_charset == &my_charset_bin)
220
270
  {
225
275
      mi_int2store(to+length-2, tot_length);
226
276
    length-= length_bytes;
227
277
  }
228
 
 
 
278
 
229
279
  tot_length= my_strnxfrm(field_charset,
230
280
                          to, length, ptr + length_bytes,
231
281
                          tot_length);
247
297
 
248
298
void Field_varstring::sql_type(String &res) const
249
299
{
250
 
  THD *thd= table->in_use;
251
300
  const CHARSET_INFO * const cs=res.charset();
252
301
  uint32_t length;
253
302
 
256
305
                              (has_charset() ? "varchar" : "varbinary"),
257
306
                             (int) field_length / charset()->mbmaxlen);
258
307
  res.length(length);
259
 
  if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
260
 
      has_charset() && (charset()->state & MY_CS_BINSORT))
261
 
    res.append(STRING_WITH_LEN(" binary"));
262
308
}
263
309
 
264
310
 
269
315
 
270
316
uint32_t Field_varstring::used_length()
271
317
{
272
 
  return length_bytes == 1 ? 1 + (uint32_t) (uchar) *ptr : 2 + uint2korr(ptr);
 
318
  return length_bytes == 1 ? 1 + (uint32_t) (unsigned char) *ptr : 2 + uint2korr(ptr);
273
319
}
274
320
 
275
321
/*
277
323
  Here the number of length bytes are depending on the given max_length
278
324
*/
279
325
 
280
 
uchar *Field_varstring::pack(uchar *to, const uchar *from,
281
 
                             uint max_length,
282
 
                             bool low_byte_first __attribute__((unused)))
 
326
unsigned char *Field_varstring::pack(unsigned char *to, const unsigned char *from,
 
327
                             uint32_t max_length,
 
328
                             bool )
283
329
{
284
 
  uint length= length_bytes == 1 ? (uint) *from : uint2korr(from);
 
330
  uint32_t length= length_bytes == 1 ? (uint32_t) *from : uint2korr(from);
285
331
  set_if_smaller(max_length, field_length);
286
332
  if (length > max_length)
287
333
    length=max_length;
298
344
}
299
345
 
300
346
 
301
 
uchar *
302
 
Field_varstring::pack_key(uchar *to, const uchar *key, uint max_length,
303
 
                          bool low_byte_first __attribute__((unused)))
 
347
unsigned char *
 
348
Field_varstring::pack_key(unsigned char *to, const unsigned char *key, uint32_t max_length,
 
349
                          bool )
304
350
{
305
 
  uint length=  length_bytes == 1 ? (uint) *key : uint2korr(key);
306
 
  uint local_char_length= ((field_charset->mbmaxlen > 1) ?
 
351
  uint32_t length=  length_bytes == 1 ? (uint32_t) *key : uint2korr(key);
 
352
  uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
307
353
                     max_length/field_charset->mbmaxlen : max_length);
308
354
  key+= length_bytes;
309
355
  if (length > local_char_length)
336
382
    Pointer to end of 'key' (To the next key part if multi-segment key)
337
383
*/
338
384
 
339
 
const uchar *
340
 
Field_varstring::unpack_key(uchar *to __attribute__((unused)),
341
 
                            const uchar *key, uint max_length,
342
 
                            bool low_byte_first __attribute__((unused)))
 
385
const unsigned char *
 
386
Field_varstring::unpack_key(unsigned char *,
 
387
                            const unsigned char *key, uint32_t max_length,
 
388
                            bool )
343
389
{
344
390
  /* get length of the blob key */
345
391
  uint32_t length= *key++;
348
394
 
349
395
  /* put the length into the record buffer */
350
396
  if (length_bytes == 1)
351
 
    *ptr= (uchar) length;
 
397
    *ptr= (unsigned char) length;
352
398
  else
353
399
    int2store(ptr, length);
354
400
  memcpy(ptr + length_bytes, key, length);
366
412
    end of key storage
367
413
*/
368
414
 
369
 
uchar *
370
 
Field_varstring::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length,
371
 
                                         bool low_byte_first __attribute__((unused)))
 
415
unsigned char *
 
416
Field_varstring::pack_key_from_key_image(unsigned char *to, const unsigned char *from, uint32_t max_length,
 
417
                                         bool )
372
418
{
373
419
  /* Key length is always stored as 2 bytes */
374
 
  uint length= uint2korr(from);
 
420
  uint32_t length= uint2korr(from);
375
421
  if (length > max_length)
376
422
    length= max_length;
377
423
  *to++= (char) (length & 255);
391
437
 
392
438
   @note
393
439
   The string length is always packed little-endian.
394
 
  
 
440
 
395
441
   @param   to         Destination of the data
396
442
   @param   from       Source of the data
397
443
   @param   param_data Length bytes from the master's field data
398
444
 
399
445
   @return  New pointer into memory based on from + length of the data
400
446
*/
401
 
const uchar *
402
 
Field_varstring::unpack(uchar *to, const uchar *from,
403
 
                        uint param_data,
404
 
                        bool low_byte_first __attribute__((unused)))
 
447
const unsigned char *
 
448
Field_varstring::unpack(unsigned char *to, const unsigned char *from,
 
449
                        uint32_t param_data,
 
450
                        bool )
405
451
{
406
 
  uint length;
407
 
  uint l_bytes= (param_data && (param_data < field_length)) ? 
 
452
  uint32_t length;
 
453
  uint32_t l_bytes= (param_data && (param_data < field_length)) ?
408
454
                (param_data <= 255) ? 1 : 2 : length_bytes;
409
455
  if (l_bytes == 1)
410
456
  {
425
471
}
426
472
 
427
473
 
428
 
int Field_varstring::pack_cmp(const uchar *a, const uchar *b,
429
 
                              uint key_length_arg,
 
474
int Field_varstring::pack_cmp(const unsigned char *a, const unsigned char *b,
 
475
                              uint32_t key_length_arg,
430
476
                              bool insert_or_update)
431
477
{
432
 
  uint a_length, b_length;
 
478
  uint32_t a_length, b_length;
433
479
  if (key_length_arg > 255)
434
480
  {
435
481
    a_length=uint2korr(a); a+= 2;
437
483
  }
438
484
  else
439
485
  {
440
 
    a_length= (uint) *a++;
441
 
    b_length= (uint) *b++;
 
486
    a_length= (uint32_t) *a++;
 
487
    b_length= (uint32_t) *b++;
442
488
  }
443
489
  return field_charset->coll->strnncollsp(field_charset,
444
490
                                          a, a_length,
447
493
}
448
494
 
449
495
 
450
 
int Field_varstring::pack_cmp(const uchar *b, uint key_length_arg,
 
496
int Field_varstring::pack_cmp(const unsigned char *b, uint32_t key_length_arg,
451
497
                              bool insert_or_update)
452
498
{
453
 
  uchar *a= ptr+ length_bytes;
454
 
  uint a_length=  length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
455
 
  uint b_length;
456
 
  uint local_char_length= ((field_charset->mbmaxlen > 1) ?
 
499
  unsigned char *a= ptr+ length_bytes;
 
500
  uint32_t a_length=  length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
 
501
  uint32_t b_length;
 
502
  uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
457
503
                           key_length_arg / field_charset->mbmaxlen :
458
504
                           key_length_arg);
459
505
 
462
508
    b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
463
509
  }
464
510
  else
465
 
    b_length= (uint) *b++;
 
511
    b_length= (uint32_t) *b++;
466
512
 
467
513
  if (a_length > local_char_length)
468
514
  {
478
524
}
479
525
 
480
526
 
481
 
uint Field_varstring::packed_col_length(const uchar *data_ptr, uint length)
 
527
uint32_t Field_varstring::packed_col_length(const unsigned char *data_ptr, uint32_t length)
482
528
{
483
529
  if (length > 255)
484
530
    return uint2korr(data_ptr)+2;
485
 
  return (uint) *data_ptr + 1;
 
531
  return (uint32_t) *data_ptr + 1;
486
532
}
487
533
 
488
534
 
489
 
uint Field_varstring::max_packed_col_length(uint max_length)
 
535
uint32_t Field_varstring::max_packed_col_length(uint32_t max_length)
490
536
{
491
537
  return (max_length > 255 ? 2 : 1)+max_length;
492
538
}
493
539
 
494
 
uint Field_varstring::get_key_image(uchar *buff,
495
 
                                    uint length,
496
 
                                    imagetype type __attribute__((unused)))
497
 
{
498
 
  uint f_length=  length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
499
 
  uint local_char_length= length / field_charset->mbmaxlen;
500
 
  uchar *pos= ptr+length_bytes;
 
540
uint32_t Field_varstring::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
 
541
{
 
542
  /* Key is always stored with 2 bytes */
 
543
  const uint32_t key_len= 2;
 
544
  uint32_t f_length=  length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
 
545
  uint32_t local_char_length= length / field_charset->mbmaxlen;
 
546
  unsigned char *pos= ptr+length_bytes;
 
547
  local_char_length= my_charpos(field_charset, pos, pos + f_length,
 
548
                                local_char_length);
 
549
  set_if_smaller(f_length, local_char_length);
 
550
  unsigned char len_buff[key_len];
 
551
  int2store(len_buff,f_length);
 
552
  buff.append(len_buff);
 
553
  buff.append(pos, f_length);
 
554
  if (f_length < length)
 
555
  {
 
556
    /*
 
557
      Must clear this as we do a memcmp in opt_range.cc to detect
 
558
      identical keys
 
559
    */
 
560
    buff.append(length-f_length, 0);
 
561
  }
 
562
  return key_len+f_length;
 
563
}
 
564
 
 
565
 
 
566
uint32_t Field_varstring::get_key_image(unsigned char *buff, uint32_t length)
 
567
{
 
568
  uint32_t f_length=  length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
 
569
  uint32_t local_char_length= length / field_charset->mbmaxlen;
 
570
  unsigned char *pos= ptr+length_bytes;
501
571
  local_char_length= my_charpos(field_charset, pos, pos + f_length,
502
572
                                local_char_length);
503
573
  set_if_smaller(f_length, local_char_length);
515
585
  return HA_KEY_BLOB_LENGTH+f_length;
516
586
}
517
587
 
518
 
 
519
 
void Field_varstring::set_key_image(const uchar *buff,uint length)
 
588
void Field_varstring::set_key_image(const unsigned char *buff, uint32_t length)
520
589
{
521
590
  length= uint2korr(buff);                      // Real length is here
522
 
  (void) Field_varstring::store((const char*) buff+HA_KEY_BLOB_LENGTH, length,
523
 
                                field_charset);
 
591
  (void) Field_varstring::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
524
592
}
525
593
 
526
 
 
527
 
int Field_varstring::cmp_binary(const uchar *a_ptr, const uchar *b_ptr,
 
594
int Field_varstring::cmp_binary(const unsigned char *a_ptr,
 
595
                                const unsigned char *b_ptr,
528
596
                                uint32_t max_length)
529
597
{
530
598
  uint32_t a_length,b_length;
531
599
 
532
600
  if (length_bytes == 1)
533
601
  {
534
 
    a_length= (uint) *a_ptr;
535
 
    b_length= (uint) *b_ptr;
 
602
    a_length= (uint32_t) *a_ptr;
 
603
    b_length= (uint32_t) *b_ptr;
536
604
  }
537
605
  else
538
606
  {
547
615
}
548
616
 
549
617
 
550
 
Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table,
551
 
                                  bool keep_type)
 
618
Field *Field_varstring::new_field(MEM_ROOT *root, Table *new_table, bool keep_type)
552
619
{
553
620
  Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table,
554
621
                                                            keep_type);
559
626
 
560
627
 
561
628
Field *Field_varstring::new_key_field(MEM_ROOT *root,
562
 
                                      struct st_table *new_table,
563
 
                                      uchar *new_ptr, uchar *new_null_ptr,
564
 
                                      uint new_null_bit)
 
629
                                      Table *new_table,
 
630
                                      unsigned char *new_ptr, unsigned char *new_null_ptr,
 
631
                                      uint32_t new_null_bit)
565
632
{
566
633
  Field_varstring *res;
567
634
  if ((res= (Field_varstring*) Field::new_key_field(root,
577
644
}
578
645
 
579
646
 
580
 
uint Field_varstring::is_equal(Create_field *new_field)
 
647
uint32_t Field_varstring::is_equal(CreateField *new_field_ptr)
581
648
{
582
 
  if (new_field->sql_type == real_type() &&
583
 
      new_field->charset == field_charset)
 
649
  if (new_field_ptr->sql_type == real_type() &&
 
650
      new_field_ptr->charset == field_charset)
584
651
  {
585
 
    if (new_field->length == max_display_length())
 
652
    if (new_field_ptr->length == max_display_length())
586
653
      return IS_EQUAL_YES;
587
 
    if (new_field->length > max_display_length() &&
588
 
        ((new_field->length <= 255 && max_display_length() <= 255) ||
589
 
         (new_field->length > 255 && max_display_length() > 255)))
 
654
    if (new_field_ptr->length > max_display_length() &&
 
655
        ((new_field_ptr->length <= 255 && max_display_length() <= 255) ||
 
656
         (new_field_ptr->length > 255 && max_display_length() > 255)))
590
657
      return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer variable length
591
658
  }
592
659
  return IS_EQUAL_NO;
601
668
  }
602
669
  else
603
670
  {
604
 
    uint32_t len=  length_bytes == 1 ? (uint) *ptr : uint2korr(ptr);
 
671
    uint32_t len=  length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
605
672
    const CHARSET_INFO * const cs= charset();
606
673
    cs->coll->hash_sort(cs, ptr + length_bytes, len, nr, nr2);
607
674
  }