~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

  • Committer: Monty Taylor
  • Date: 2008-07-05 22:08:52 UTC
  • mto: This revision was merged to the branch mainline in revision 77.
  • Revision ID: monty@inaugust.com-20080705220852-cqd9t6tfkhvlcf73
Removed HAVE_LONG_LONG, as this is now assumed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 MySQL
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; either version 2 of the License, or
9
 
 *  (at your option) any later version.
10
 
 *
11
 
 *  This program is distributed in the hope that it will be useful,
12
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with this program; if not, write to the Free Software
18
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
 
 */
20
 
 
21
 
 
22
 
#include <drizzled/server_includes.h>
23
 
#include <drizzled/field/blob.h>
24
 
 
25
 
uint32_t
26
 
blob_pack_length_to_max_length(uint32_t arg)
27
 
{
28
 
  return (INT64_C(1) << cmin(arg, 4U) * 8) - INT64_C(1);
29
 
}
30
 
 
31
 
 
32
 
/****************************************************************************
33
 
** blob type
34
 
** A blob is saved as a length and a pointer. The length is stored in the
35
 
** packlength slot and may be from 1-4.
36
 
****************************************************************************/
37
 
 
38
 
Field_blob::Field_blob(unsigned char *ptr_arg, unsigned char *null_ptr_arg, unsigned char null_bit_arg,
39
 
                       enum utype unireg_check_arg, const char *field_name_arg,
40
 
                       TABLE_SHARE *share, uint32_t blob_pack_length,
41
 
                       const CHARSET_INFO * const cs)
42
 
  :Field_longstr(ptr_arg, blob_pack_length_to_max_length(blob_pack_length),
43
 
                 null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
44
 
                 cs),
45
 
   packlength(blob_pack_length)
46
 
{
47
 
  flags|= BLOB_FLAG;
48
 
  share->blob_fields++;
49
 
  /* TODO: why do not fill table->s->blob_field array here? */
50
 
}
51
 
 
52
 
 
53
 
void Field_blob::store_length(unsigned char *i_ptr,
54
 
                              uint32_t i_packlength,
55
 
                              uint32_t i_number,
56
 
                              bool low_byte_first __attribute__((unused)))
57
 
{
58
 
  switch (i_packlength) {
59
 
  case 1:
60
 
    i_ptr[0]= (unsigned char) i_number;
61
 
    break;
62
 
  case 2:
63
 
#ifdef WORDS_BIGENDIAN
64
 
    if (low_byte_first)
65
 
    {
66
 
      int2store(i_ptr,(unsigned short) i_number);
67
 
    }
68
 
    else
69
 
#endif
70
 
      shortstore(i_ptr,(unsigned short) i_number);
71
 
    break;
72
 
  case 3:
73
 
    int3store(i_ptr,i_number);
74
 
    break;
75
 
  case 4:
76
 
#ifdef WORDS_BIGENDIAN
77
 
    if (low_byte_first)
78
 
    {
79
 
      int4store(i_ptr,i_number);
80
 
    }
81
 
    else
82
 
#endif
83
 
      longstore(i_ptr,i_number);
84
 
  }
85
 
}
86
 
 
87
 
 
88
 
uint32_t Field_blob::get_length(const unsigned char *pos,
89
 
                              uint32_t packlength_arg,
90
 
                              bool low_byte_first __attribute__((unused)))
91
 
{
92
 
  switch (packlength_arg) {
93
 
  case 1:
94
 
    return (uint32_t) pos[0];
95
 
  case 2:
96
 
    {
97
 
      uint16_t tmp;
98
 
#ifdef WORDS_BIGENDIAN
99
 
      if (low_byte_first)
100
 
        tmp=sint2korr(pos);
101
 
      else
102
 
#endif
103
 
        shortget(tmp,pos);
104
 
      return (uint32_t) tmp;
105
 
    }
106
 
  case 3:
107
 
    return (uint32_t) uint3korr(pos);
108
 
  case 4:
109
 
    {
110
 
      uint32_t tmp;
111
 
#ifdef WORDS_BIGENDIAN
112
 
      if (low_byte_first)
113
 
        tmp=uint4korr(pos);
114
 
      else
115
 
#endif
116
 
        longget(tmp,pos);
117
 
      return (uint32_t) tmp;
118
 
    }
119
 
  }
120
 
  return 0;                                     // Impossible
121
 
}
122
 
 
123
 
 
124
 
/**
125
 
  Put a blob length field into a record buffer.
126
 
 
127
 
  Depending on the maximum length of a blob, its length field is
128
 
  put into 1 to 4 bytes. This is a property of the blob object,
129
 
  described by 'packlength'.
130
 
 
131
 
  @param pos                 Pointer into the record buffer.
132
 
  @param length              The length value to put.
133
 
*/
134
 
 
135
 
void Field_blob::put_length(unsigned char *pos, uint32_t length)
136
 
{
137
 
  switch (packlength) {
138
 
  case 1:
139
 
    *pos= (char) length;
140
 
    break;
141
 
  case 2:
142
 
    int2store(pos, length);
143
 
    break;
144
 
  case 3:
145
 
    int3store(pos, length);
146
 
    break;
147
 
  case 4:
148
 
    int4store(pos, length);
149
 
    break;
150
 
  }
151
 
}
152
 
 
153
 
 
154
 
int Field_blob::store(const char *from,uint32_t length, const CHARSET_INFO * const cs)
155
 
{
156
 
  uint32_t copy_length, new_length;
157
 
  const char *well_formed_error_pos;
158
 
  const char *cannot_convert_error_pos;
159
 
  const char *from_end_pos, *tmp;
160
 
  char buff[STRING_BUFFER_USUAL_SIZE];
161
 
  String tmpstr(buff,sizeof(buff), &my_charset_bin);
162
 
 
163
 
  if (!length)
164
 
  {
165
 
    memset(ptr, 0, Field_blob::pack_length());
166
 
    return 0;
167
 
  }
168
 
 
169
 
  if (from == value.ptr())
170
 
  {
171
 
    uint32_t dummy_offset;
172
 
    if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
173
 
    {
174
 
      Field_blob::store_length(length);
175
 
      memcpy(ptr+packlength, &from, sizeof(char*));
176
 
      return 0;
177
 
    }
178
 
    if (tmpstr.copy(from, length, cs))
179
 
      goto oom_error;
180
 
    from= tmpstr.ptr();
181
 
  }
182
 
 
183
 
  new_length= cmin(max_data_length(), field_charset->mbmaxlen * length);
184
 
  if (value.alloc(new_length))
185
 
    goto oom_error;
186
 
 
187
 
 
188
 
  if (f_is_hex_escape(flags))
189
 
  {
190
 
    copy_length= my_copy_with_hex_escaping(field_charset,
191
 
                                           (char*) value.ptr(), new_length,
192
 
                                            from, length);
193
 
    Field_blob::store_length(copy_length);
194
 
    tmp= value.ptr();
195
 
    memcpy(ptr + packlength, &tmp, sizeof(char*));
196
 
    return 0;
197
 
  }
198
 
  /*
199
 
    "length" is OK as "nchars" argument to well_formed_copy_nchars as this
200
 
    is never used to limit the length of the data. The cut of long data
201
 
    is done with the new_length value.
202
 
  */
203
 
  copy_length= well_formed_copy_nchars(field_charset,
204
 
                                       (char*) value.ptr(), new_length,
205
 
                                       cs, from, length,
206
 
                                       length,
207
 
                                       &well_formed_error_pos,
208
 
                                       &cannot_convert_error_pos,
209
 
                                       &from_end_pos);
210
 
 
211
 
  Field_blob::store_length(copy_length);
212
 
  tmp= value.ptr();
213
 
  memcpy(ptr+packlength, &tmp, sizeof(char*));
214
 
 
215
 
  if (check_string_copy_error(this, well_formed_error_pos,
216
 
                              cannot_convert_error_pos, from + length, cs))
217
 
    return 2;
218
 
 
219
 
  return report_if_important_data(from_end_pos, from + length);
220
 
 
221
 
oom_error:
222
 
  /* Fatal OOM error */
223
 
  memset(ptr, 0, Field_blob::pack_length());
224
 
  return -1; 
225
 
}
226
 
 
227
 
 
228
 
int Field_blob::store(double nr)
229
 
{
230
 
  const CHARSET_INFO * const cs=charset();
231
 
  value.set_real(nr, NOT_FIXED_DEC, cs);
232
 
  return Field_blob::store(value.ptr(),(uint) value.length(), cs);
233
 
}
234
 
 
235
 
 
236
 
int Field_blob::store(int64_t nr, bool unsigned_val)
237
 
{
238
 
  const CHARSET_INFO * const cs=charset();
239
 
  value.set_int(nr, unsigned_val, cs);
240
 
  return Field_blob::store(value.ptr(), (uint) value.length(), cs);
241
 
}
242
 
 
243
 
 
244
 
double Field_blob::val_real(void)
245
 
{
246
 
  int not_used;
247
 
  char *end_not_used, *blob;
248
 
  uint32_t length;
249
 
  const CHARSET_INFO *cs;
250
 
 
251
 
  memcpy(&blob,ptr+packlength,sizeof(char*));
252
 
  if (!blob)
253
 
    return 0.0;
254
 
  length= get_length(ptr);
255
 
  cs= charset();
256
 
  return my_strntod(cs, blob, length, &end_not_used, &not_used);
257
 
}
258
 
 
259
 
 
260
 
int64_t Field_blob::val_int(void)
261
 
{
262
 
  int not_used;
263
 
  char *blob;
264
 
  memcpy(&blob,ptr+packlength,sizeof(char*));
265
 
  if (!blob)
266
 
    return 0;
267
 
  uint32_t length=get_length(ptr);
268
 
  return my_strntoll(charset(),blob,length,10,NULL,&not_used);
269
 
}
270
 
 
271
 
String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
272
 
                            String *val_ptr)
273
 
{
274
 
  char *blob;
275
 
  memcpy(&blob,ptr+packlength,sizeof(char*));
276
 
  if (!blob)
277
 
    val_ptr->set("",0,charset());       // A bit safer than ->length(0)
278
 
  else
279
 
    val_ptr->set((const char*) blob,get_length(ptr),charset());
280
 
  return val_ptr;
281
 
}
282
 
 
283
 
 
284
 
my_decimal *Field_blob::val_decimal(my_decimal *decimal_value)
285
 
{
286
 
  const char *blob;
287
 
  size_t length;
288
 
  memcpy(&blob, ptr+packlength, sizeof(const unsigned char*));
289
 
  if (!blob)
290
 
  {
291
 
    blob= "";
292
 
    length= 0;
293
 
  }
294
 
  else
295
 
    length= get_length(ptr);
296
 
 
297
 
  str2my_decimal(E_DEC_FATAL_ERROR, blob, length, charset(),
298
 
                 decimal_value);
299
 
  return decimal_value;
300
 
}
301
 
 
302
 
 
303
 
int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
304
 
                    uint32_t b_length)
305
 
{
306
 
  return field_charset->coll->strnncollsp(field_charset, 
307
 
                                          a, a_length, b, b_length,
308
 
                                          0);
309
 
}
310
 
 
311
 
 
312
 
int Field_blob::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
313
 
                        uint32_t max_length)
314
 
{
315
 
  unsigned char *blob1,*blob2;
316
 
  memcpy(&blob1,a_ptr+packlength,sizeof(char*));
317
 
  memcpy(&blob2,b_ptr+packlength,sizeof(char*));
318
 
  uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
319
 
  set_if_smaller(a_len, max_length);
320
 
  set_if_smaller(b_len, max_length);
321
 
  return Field_blob::cmp(blob1,a_len,blob2,b_len);
322
 
}
323
 
 
324
 
 
325
 
int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
326
 
                           uint32_t max_length)
327
 
{
328
 
  char *a,*b;
329
 
  uint32_t diff;
330
 
  uint32_t a_length,b_length;
331
 
  memcpy(&a,a_ptr+packlength,sizeof(char*));
332
 
  memcpy(&b,b_ptr+packlength,sizeof(char*));
333
 
  a_length=get_length(a_ptr);
334
 
  if (a_length > max_length)
335
 
    a_length=max_length;
336
 
  b_length=get_length(b_ptr);
337
 
  if (b_length > max_length)
338
 
    b_length=max_length;
339
 
  diff=memcmp(a,b,cmin(a_length,b_length));
340
 
  return diff ? diff : (int) (a_length - b_length);
341
 
}
342
 
 
343
 
 
344
 
/* The following is used only when comparing a key */
345
 
 
346
 
uint32_t Field_blob::get_key_image(unsigned char *buff,
347
 
                               uint32_t length,
348
 
                               imagetype type_arg __attribute__((unused)))
349
 
{
350
 
  uint32_t blob_length= get_length(ptr);
351
 
  unsigned char *blob;
352
 
 
353
 
  get_ptr(&blob);
354
 
  uint32_t local_char_length= length / field_charset->mbmaxlen;
355
 
  local_char_length= my_charpos(field_charset, blob, blob + blob_length,
356
 
                          local_char_length);
357
 
  set_if_smaller(blob_length, local_char_length);
358
 
 
359
 
  if ((uint32_t) length > blob_length)
360
 
  {
361
 
    /*
362
 
      Must clear this as we do a memcmp in opt_range.cc to detect
363
 
      identical keys
364
 
    */
365
 
    memset(buff+HA_KEY_BLOB_LENGTH+blob_length, 0, (length-blob_length));
366
 
    length=(uint) blob_length;
367
 
  }
368
 
  int2store(buff,length);
369
 
  memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
370
 
  return HA_KEY_BLOB_LENGTH+length;
371
 
}
372
 
 
373
 
 
374
 
void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
375
 
{
376
 
  length= uint2korr(buff);
377
 
  (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length,
378
 
                           field_charset);
379
 
}
380
 
 
381
 
 
382
 
int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
383
 
{
384
 
  unsigned char *blob1;
385
 
  uint32_t blob_length=get_length(ptr);
386
 
  memcpy(&blob1,ptr+packlength,sizeof(char*));
387
 
  const CHARSET_INFO * const cs= charset();
388
 
  uint32_t local_char_length= max_key_length / cs->mbmaxlen;
389
 
  local_char_length= my_charpos(cs, blob1, blob1+blob_length,
390
 
                                local_char_length);
391
 
  set_if_smaller(blob_length, local_char_length);
392
 
  return Field_blob::cmp(blob1, blob_length,
393
 
                         key_ptr+HA_KEY_BLOB_LENGTH,
394
 
                         uint2korr(key_ptr));
395
 
}
396
 
 
397
 
int Field_blob::key_cmp(const unsigned char *a,const unsigned char *b)
398
 
{
399
 
  return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
400
 
                         b+HA_KEY_BLOB_LENGTH, uint2korr(b));
401
 
}
402
 
 
403
 
 
404
 
/**
405
 
   Save the field metadata for blob fields.
406
 
 
407
 
   Saves the pack length in the first byte of the field metadata array
408
 
   at index of *metadata_ptr.
409
 
 
410
 
   @param   metadata_ptr   First byte of field metadata
411
 
 
412
 
   @returns number of bytes written to metadata_ptr
413
 
*/
414
 
int Field_blob::do_save_field_metadata(unsigned char *metadata_ptr)
415
 
{
416
 
  *metadata_ptr= pack_length_no_ptr();
417
 
  return 1;
418
 
}
419
 
 
420
 
 
421
 
uint32_t Field_blob::sort_length() const
422
 
{
423
 
  return (uint32_t) (current_thd->variables.max_sort_length + 
424
 
                   (field_charset == &my_charset_bin ? 0 : packlength));
425
 
}
426
 
 
427
 
 
428
 
void Field_blob::sort_string(unsigned char *to,uint32_t length)
429
 
{
430
 
  unsigned char *blob;
431
 
  uint32_t blob_length=get_length();
432
 
 
433
 
  if (!blob_length)
434
 
    memset(to, 0, length);
435
 
  else
436
 
  {
437
 
    if (field_charset == &my_charset_bin)
438
 
    {
439
 
      unsigned char *pos;
440
 
 
441
 
      /*
442
 
        Store length of blob last in blob to shorter blobs before longer blobs
443
 
      */
444
 
      length-= packlength;
445
 
      pos= to+length;
446
 
 
447
 
      switch (packlength) {
448
 
      case 1:
449
 
        *pos= (char) blob_length;
450
 
        break;
451
 
      case 2:
452
 
        mi_int2store(pos, blob_length);
453
 
        break;
454
 
      case 3:
455
 
        mi_int3store(pos, blob_length);
456
 
        break;
457
 
      case 4:
458
 
        mi_int4store(pos, blob_length);
459
 
        break;
460
 
      }
461
 
    }
462
 
    memcpy(&blob,ptr+packlength,sizeof(char*));
463
 
    
464
 
    blob_length=my_strnxfrm(field_charset,
465
 
                            to, length, blob, blob_length);
466
 
    assert(blob_length == length);
467
 
  }
468
 
}
469
 
 
470
 
 
471
 
void Field_blob::sql_type(String &res) const
472
 
{
473
 
  if (charset() == &my_charset_bin)
474
 
    res.set_ascii(STRING_WITH_LEN("blob"));
475
 
  else
476
 
    res.set_ascii(STRING_WITH_LEN("text"));
477
 
}
478
 
 
479
 
unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
480
 
                        uint32_t max_length, bool low_byte_first)
481
 
{
482
 
  unsigned char *save= ptr;
483
 
  ptr= (unsigned char*) from;
484
 
  uint32_t length=get_length();                 // Length of from string
485
 
 
486
 
  /*
487
 
    Store max length, which will occupy packlength bytes. If the max
488
 
    length given is smaller than the actual length of the blob, we
489
 
    just store the initial bytes of the blob.
490
 
  */
491
 
  store_length(to, packlength, cmin(length, max_length), low_byte_first);
492
 
 
493
 
  /*
494
 
    Store the actual blob data, which will occupy 'length' bytes.
495
 
   */
496
 
  if (length > 0)
497
 
  {
498
 
    get_ptr((unsigned char**) &from);
499
 
    memcpy(to+packlength, from,length);
500
 
  }
501
 
  ptr=save;                                     // Restore org row pointer
502
 
  return(to+packlength+length);
503
 
}
504
 
 
505
 
 
506
 
/**
507
 
   Unpack a blob field from row data.
508
 
 
509
 
   This method is used to unpack a blob field from a master whose size of 
510
 
   the field is less than that of the slave. Note: This method is included
511
 
   to satisfy inheritance rules, but is not needed for blob fields. It
512
 
   simply is used as a pass-through to the original unpack() method for
513
 
   blob fields.
514
 
 
515
 
   @param   to         Destination of the data
516
 
   @param   from       Source of the data
517
 
   @param   param_data @c true if base types should be stored in little-
518
 
                       endian format, @c false if native format should
519
 
                       be used.
520
 
 
521
 
   @return  New pointer into memory based on from + length of the data
522
 
*/
523
 
const unsigned char *Field_blob::unpack(unsigned char *to __attribute__((unused)),
524
 
                                const unsigned char *from,
525
 
                                uint32_t param_data,
526
 
                                bool low_byte_first)
527
 
{
528
 
  uint32_t const master_packlength=
529
 
    param_data > 0 ? param_data & 0xFF : packlength;
530
 
  uint32_t const length= get_length(from, master_packlength, low_byte_first);
531
 
  bitmap_set_bit(table->write_set, field_index);
532
 
  store(reinterpret_cast<const char*>(from) + master_packlength,
533
 
        length, field_charset);
534
 
  return(from + master_packlength + length);
535
 
}
536
 
 
537
 
/* Keys for blobs are like keys on varchars */
538
 
 
539
 
int Field_blob::pack_cmp(const unsigned char *a, const unsigned char *b, uint32_t key_length_arg,
540
 
                         bool insert_or_update)
541
 
{
542
 
  uint32_t a_length, b_length;
543
 
  if (key_length_arg > 255)
544
 
  {
545
 
    a_length=uint2korr(a); a+=2;
546
 
    b_length=uint2korr(b); b+=2;
547
 
  }
548
 
  else
549
 
  {
550
 
    a_length= (uint) *a++;
551
 
    b_length= (uint) *b++;
552
 
  }
553
 
  return field_charset->coll->strnncollsp(field_charset,
554
 
                                          a, a_length,
555
 
                                          b, b_length,
556
 
                                          insert_or_update);
557
 
}
558
 
 
559
 
 
560
 
int Field_blob::pack_cmp(const unsigned char *b, uint32_t key_length_arg,
561
 
                         bool insert_or_update)
562
 
{
563
 
  unsigned char *a;
564
 
  uint32_t a_length, b_length;
565
 
  memcpy(&a,ptr+packlength,sizeof(char*));
566
 
  if (!a)
567
 
    return key_length_arg > 0 ? -1 : 0;
568
 
 
569
 
  a_length= get_length(ptr);
570
 
  if (key_length_arg > 255)
571
 
  {
572
 
    b_length= uint2korr(b); b+=2;
573
 
  }
574
 
  else
575
 
    b_length= (uint) *b++;
576
 
  return field_charset->coll->strnncollsp(field_charset,
577
 
                                          a, a_length,
578
 
                                          b, b_length,
579
 
                                          insert_or_update);
580
 
}
581
 
 
582
 
/** Create a packed key that will be used for storage from a MySQL row. */
583
 
 
584
 
unsigned char *
585
 
Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
586
 
                     bool low_byte_first __attribute__((unused)))
587
 
{
588
 
  unsigned char *save= ptr;
589
 
  ptr= (unsigned char*) from;
590
 
  uint32_t length=get_length();        // Length of from string
591
 
  uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
592
 
                           max_length/field_charset->mbmaxlen : max_length);
593
 
  if (length)
594
 
    get_ptr((unsigned char**) &from);
595
 
  if (length > local_char_length)
596
 
    local_char_length= my_charpos(field_charset, from, from+length,
597
 
                                  local_char_length);
598
 
  set_if_smaller(length, local_char_length);
599
 
  *to++= (unsigned char) length;
600
 
  if (max_length > 255)                         // 2 byte length
601
 
    *to++= (unsigned char) (length >> 8);
602
 
  memcpy(to, from, length);
603
 
  ptr=save;                                     // Restore org row pointer
604
 
  return to+length;
605
 
}
606
 
 
607
 
 
608
 
/**
609
 
  Unpack a blob key into a record buffer.
610
 
 
611
 
  A blob key has a maximum size of 64K-1.
612
 
  In its packed form, the length field is one or two bytes long,
613
 
  depending on 'max_length'.
614
 
  Depending on the maximum length of a blob, its length field is
615
 
  put into 1 to 4 bytes. This is a property of the blob object,
616
 
  described by 'packlength'.
617
 
  Blobs are internally stored apart from the record buffer, which
618
 
  contains a pointer to the blob buffer.
619
 
 
620
 
 
621
 
  @param to                          Pointer into the record buffer.
622
 
  @param from                        Pointer to the packed key.
623
 
  @param max_length                  Key length limit from key description.
624
 
 
625
 
  @return
626
 
    Pointer into 'from' past the last byte copied from packed key.
627
 
*/
628
 
 
629
 
const unsigned char *
630
 
Field_blob::unpack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
631
 
                       bool low_byte_first __attribute__((unused)))
632
 
{
633
 
  /* get length of the blob key */
634
 
  uint32_t length= *from++;
635
 
  if (max_length > 255)
636
 
    length+= *from++ << 8;
637
 
 
638
 
  /* put the length into the record buffer */
639
 
  put_length(to, length);
640
 
 
641
 
  /* put the address of the blob buffer or NULL */
642
 
  if (length)
643
 
    memcpy(to + packlength, &from, sizeof(from));
644
 
  else
645
 
    memset(to + packlength, 0, sizeof(from));
646
 
 
647
 
  /* point to first byte of next field in 'from' */
648
 
  return from + length;
649
 
}
650
 
 
651
 
 
652
 
/** Create a packed key that will be used for storage from a MySQL key. */
653
 
 
654
 
unsigned char *
655
 
Field_blob::pack_key_from_key_image(unsigned char *to, const unsigned char *from, uint32_t max_length,
656
 
                                    bool low_byte_first __attribute__((unused)))
657
 
{
658
 
  uint32_t length=uint2korr(from);
659
 
  if (length > max_length)
660
 
    length=max_length;
661
 
  *to++= (char) (length & 255);
662
 
  if (max_length > 255)
663
 
    *to++= (char) (length >> 8);
664
 
  if (length)
665
 
    memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
666
 
  return to+length;
667
 
}
668
 
 
669
 
 
670
 
uint32_t Field_blob::packed_col_length(const unsigned char *data_ptr, uint32_t length)
671
 
{
672
 
  if (length > 255)
673
 
    return uint2korr(data_ptr)+2;
674
 
  return (uint) *data_ptr + 1;
675
 
}
676
 
 
677
 
 
678
 
uint32_t Field_blob::max_packed_col_length(uint32_t max_length)
679
 
{
680
 
  return (max_length > 255 ? 2 : 1)+max_length;
681
 
}
682
 
 
683
 
 
684
 
uint32_t Field_blob::is_equal(Create_field *new_field)
685
 
{
686
 
  if (compare_str_field_flags(new_field, flags))
687
 
    return 0;
688
 
 
689
 
  return ((new_field->sql_type == get_blob_type_from_length(max_data_length()))
690
 
          && new_field->charset == field_charset &&
691
 
          ((Field_blob *)new_field->field)->max_data_length() ==
692
 
          max_data_length());
693
 
}
694
 
 
695
 
 
696
 
/**
697
 
  maximum possible display length for blob.
698
 
 
699
 
  @return
700
 
    length
701
 
*/
702
 
 
703
 
uint32_t Field_blob::max_display_length()
704
 
{
705
 
  switch (packlength)
706
 
  {
707
 
  case 1:
708
 
    return 255 * field_charset->mbmaxlen;
709
 
  case 2:
710
 
    return 65535 * field_charset->mbmaxlen;
711
 
  case 3:
712
 
    return 16777215 * field_charset->mbmaxlen;
713
 
  case 4:
714
 
    return (uint32_t) 4294967295U;
715
 
  default:
716
 
    assert(0); // we should never go here
717
 
    return 0;
718
 
  }
719
 
}
720