~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

Removed reference to aio.h - we don't reference its use anywhere.

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