~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/field/blob.cc

  • Committer: Toru Maesaka
  • Date: 2008-07-17 05:59:20 UTC
  • mto: (202.1.1 toru)
  • mto: This revision was merged to the branch mainline in revision 204.
  • Revision ID: dev@torum.net-20080717055920-10okif50x6nh7b1d
forgot to bzr-add new files in the previous push

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