~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

  • Committer: Brian Aker
  • Date: 2008-07-14 16:24:25 UTC
  • Revision ID: brian@tangent.org-20080714162425-juw3vw221gs9kysh
Cleanup around intptr_t

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