~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

  • Committer: Monty Taylor
  • Date: 2008-10-16 06:32:30 UTC
  • mto: (511.1.5 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081016063230-4brxsra0qsmsg84q
Added -Wunused-macros.

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