~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

Merged build changes from Antony.

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/field/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_t 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
    memset(ptr, 0, 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
      memcpy(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
    memcpy(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
  memcpy(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
  memset(ptr, 0, 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(&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(&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(&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(&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(&blob1,a_ptr+packlength,sizeof(char*));
 
315
  memcpy(&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(&a,a_ptr+packlength,sizeof(char*));
 
330
  memcpy(&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
    memset(buff+HA_KEY_BLOB_LENGTH+blob_length, 0, (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(&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
    memset(to, 0, 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(&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
  if (charset() == &my_charset_bin)
 
472
    res.set_ascii(STRING_WITH_LEN("blob"));
 
473
  else
 
474
    res.set_ascii(STRING_WITH_LEN("text"));
 
475
}
 
476
 
 
477
uchar *Field_blob::pack(uchar *to, const uchar *from,
 
478
                        uint max_length, bool low_byte_first)
 
479
{
 
480
  uchar *save= ptr;
 
481
  ptr= (uchar*) from;
 
482
  uint32_t length=get_length();                 // Length of from string
 
483
 
 
484
  /*
 
485
    Store max length, which will occupy packlength bytes. If the max
 
486
    length given is smaller than the actual length of the blob, we
 
487
    just store the initial bytes of the blob.
 
488
  */
 
489
  store_length(to, packlength, min(length, max_length), low_byte_first);
 
490
 
 
491
  /*
 
492
    Store the actual blob data, which will occupy 'length' bytes.
 
493
   */
 
494
  if (length > 0)
 
495
  {
 
496
    get_ptr((uchar**) &from);
 
497
    memcpy(to+packlength, from,length);
 
498
  }
 
499
  ptr=save;                                     // Restore org row pointer
 
500
  return(to+packlength+length);
 
501
}
 
502
 
 
503
 
 
504
/**
 
505
   Unpack a blob field from row data.
 
506
 
 
507
   This method is used to unpack a blob field from a master whose size of 
 
508
   the field is less than that of the slave. Note: This method is included
 
509
   to satisfy inheritance rules, but is not needed for blob fields. It
 
510
   simply is used as a pass-through to the original unpack() method for
 
511
   blob fields.
 
512
 
 
513
   @param   to         Destination of the data
 
514
   @param   from       Source of the data
 
515
   @param   param_data @c true if base types should be stored in little-
 
516
                       endian format, @c false if native format should
 
517
                       be used.
 
518
 
 
519
   @return  New pointer into memory based on from + length of the data
 
520
*/
 
521
const uchar *Field_blob::unpack(uchar *to __attribute__((unused)),
 
522
                                const uchar *from,
 
523
                                uint param_data,
 
524
                                bool low_byte_first)
 
525
{
 
526
  uint const master_packlength=
 
527
    param_data > 0 ? param_data & 0xFF : packlength;
 
528
  uint32_t const length= get_length(from, master_packlength, low_byte_first);
 
529
  bitmap_set_bit(table->write_set, field_index);
 
530
  store(reinterpret_cast<const char*>(from) + master_packlength,
 
531
        length, field_charset);
 
532
  return(from + master_packlength + length);
 
533
}
 
534
 
 
535
/* Keys for blobs are like keys on varchars */
 
536
 
 
537
int Field_blob::pack_cmp(const uchar *a, const uchar *b, uint key_length_arg,
 
538
                         my_bool insert_or_update)
 
539
{
 
540
  uint a_length, b_length;
 
541
  if (key_length_arg > 255)
 
542
  {
 
543
    a_length=uint2korr(a); a+=2;
 
544
    b_length=uint2korr(b); b+=2;
 
545
  }
 
546
  else
 
547
  {
 
548
    a_length= (uint) *a++;
 
549
    b_length= (uint) *b++;
 
550
  }
 
551
  return field_charset->coll->strnncollsp(field_charset,
 
552
                                          a, a_length,
 
553
                                          b, b_length,
 
554
                                          insert_or_update);
 
555
}
 
556
 
 
557
 
 
558
int Field_blob::pack_cmp(const uchar *b, uint key_length_arg,
 
559
                         my_bool insert_or_update)
 
560
{
 
561
  uchar *a;
 
562
  uint a_length, b_length;
 
563
  memcpy(&a,ptr+packlength,sizeof(char*));
 
564
  if (!a)
 
565
    return key_length_arg > 0 ? -1 : 0;
 
566
 
 
567
  a_length= get_length(ptr);
 
568
  if (key_length_arg > 255)
 
569
  {
 
570
    b_length= uint2korr(b); b+=2;
 
571
  }
 
572
  else
 
573
    b_length= (uint) *b++;
 
574
  return field_charset->coll->strnncollsp(field_charset,
 
575
                                          a, a_length,
 
576
                                          b, b_length,
 
577
                                          insert_or_update);
 
578
}
 
579
 
 
580
/** Create a packed key that will be used for storage from a MySQL row. */
 
581
 
 
582
uchar *
 
583
Field_blob::pack_key(uchar *to, const uchar *from, uint max_length,
 
584
                     bool low_byte_first __attribute__((unused)))
 
585
{
 
586
  uchar *save= ptr;
 
587
  ptr= (uchar*) from;
 
588
  uint32_t length=get_length();        // Length of from string
 
589
  uint local_char_length= ((field_charset->mbmaxlen > 1) ?
 
590
                           max_length/field_charset->mbmaxlen : max_length);
 
591
  if (length)
 
592
    get_ptr((uchar**) &from);
 
593
  if (length > local_char_length)
 
594
    local_char_length= my_charpos(field_charset, from, from+length,
 
595
                                  local_char_length);
 
596
  set_if_smaller(length, local_char_length);
 
597
  *to++= (uchar) length;
 
598
  if (max_length > 255)                         // 2 byte length
 
599
    *to++= (uchar) (length >> 8);
 
600
  memcpy(to, from, length);
 
601
  ptr=save;                                     // Restore org row pointer
 
602
  return to+length;
 
603
}
 
604
 
 
605
 
 
606
/**
 
607
  Unpack a blob key into a record buffer.
 
608
 
 
609
  A blob key has a maximum size of 64K-1.
 
610
  In its packed form, the length field is one or two bytes long,
 
611
  depending on 'max_length'.
 
612
  Depending on the maximum length of a blob, its length field is
 
613
  put into 1 to 4 bytes. This is a property of the blob object,
 
614
  described by 'packlength'.
 
615
  Blobs are internally stored apart from the record buffer, which
 
616
  contains a pointer to the blob buffer.
 
617
 
 
618
 
 
619
  @param to                          Pointer into the record buffer.
 
620
  @param from                        Pointer to the packed key.
 
621
  @param max_length                  Key length limit from key description.
 
622
 
 
623
  @return
 
624
    Pointer into 'from' past the last byte copied from packed key.
 
625
*/
 
626
 
 
627
const uchar *
 
628
Field_blob::unpack_key(uchar *to, const uchar *from, uint max_length,
 
629
                       bool low_byte_first __attribute__((unused)))
 
630
{
 
631
  /* get length of the blob key */
 
632
  uint32_t length= *from++;
 
633
  if (max_length > 255)
 
634
    length+= *from++ << 8;
 
635
 
 
636
  /* put the length into the record buffer */
 
637
  put_length(to, length);
 
638
 
 
639
  /* put the address of the blob buffer or NULL */
 
640
  if (length)
 
641
    memcpy(to + packlength, &from, sizeof(from));
 
642
  else
 
643
    memset(to + packlength, 0, sizeof(from));
 
644
 
 
645
  /* point to first byte of next field in 'from' */
 
646
  return from + length;
 
647
}
 
648
 
 
649
 
 
650
/** Create a packed key that will be used for storage from a MySQL key. */
 
651
 
 
652
uchar *
 
653
Field_blob::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length,
 
654
                                    bool low_byte_first __attribute__((unused)))
 
655
{
 
656
  uint length=uint2korr(from);
 
657
  if (length > max_length)
 
658
    length=max_length;
 
659
  *to++= (char) (length & 255);
 
660
  if (max_length > 255)
 
661
    *to++= (char) (length >> 8);
 
662
  if (length)
 
663
    memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
 
664
  return to+length;
 
665
}
 
666
 
 
667
 
 
668
uint Field_blob::packed_col_length(const uchar *data_ptr, uint length)
 
669
{
 
670
  if (length > 255)
 
671
    return uint2korr(data_ptr)+2;
 
672
  return (uint) *data_ptr + 1;
 
673
}
 
674
 
 
675
 
 
676
uint Field_blob::max_packed_col_length(uint max_length)
 
677
{
 
678
  return (max_length > 255 ? 2 : 1)+max_length;
 
679
}
 
680
 
 
681
 
 
682
uint Field_blob::is_equal(Create_field *new_field)
 
683
{
 
684
  if (compare_str_field_flags(new_field, flags))
 
685
    return 0;
 
686
 
 
687
  return ((new_field->sql_type == get_blob_type_from_length(max_data_length()))
 
688
          && new_field->charset == field_charset &&
 
689
          ((Field_blob *)new_field->field)->max_data_length() ==
 
690
          max_data_length());
 
691
}
 
692
 
 
693
 
 
694
/**
 
695
  maximum possible display length for blob.
 
696
 
 
697
  @return
 
698
    length
 
699
*/
 
700
 
 
701
uint32_t Field_blob::max_display_length()
 
702
{
 
703
  switch (packlength)
 
704
  {
 
705
  case 1:
 
706
    return 255 * field_charset->mbmaxlen;
 
707
  case 2:
 
708
    return 65535 * field_charset->mbmaxlen;
 
709
  case 3:
 
710
    return 16777215 * field_charset->mbmaxlen;
 
711
  case 4:
 
712
    return (uint32_t) 4294967295U;
 
713
  default:
 
714
    assert(0); // we should never go here
 
715
    return 0;
 
716
  }
 
717
}
 
718