~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

Merge Joe, plus I updated the tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
43
43
/****************************************************************************
44
44
** blob type
45
45
** A blob is saved as a length and a pointer. The length is stored in the
46
 
** packlength slot and is sizeof(uint32_t) (4 bytes)
 
46
** packlength slot and may be from 1-4.
47
47
****************************************************************************/
48
48
 
49
49
Field_blob::Field_blob(unsigned char *ptr_arg,
51
51
                       unsigned char null_bit_arg,
52
52
                                   const char *field_name_arg,
53
53
                       TableShare *share,
 
54
                       uint32_t blob_pack_length,
54
55
                       const CHARSET_INFO * const cs)
55
56
  :Field_str(ptr_arg,
56
 
             blob_pack_length_to_max_length(sizeof(uint32_t)),
 
57
             blob_pack_length_to_max_length(blob_pack_length),
57
58
             null_ptr_arg,
58
59
             null_bit_arg,
59
60
             field_name_arg,
60
 
             cs)
 
61
             cs),
 
62
   packlength(blob_pack_length)
61
63
{
62
64
  flags|= BLOB_FLAG;
63
65
  share->blob_fields++;
65
67
}
66
68
 
67
69
void Field_blob::store_length(unsigned char *i_ptr,
 
70
                              uint32_t i_packlength,
68
71
                              uint32_t i_number,
69
72
                              bool low_byte_first)
70
73
{
71
74
#ifndef WORDS_BIGENDIAN
72
75
  (void)low_byte_first;
73
76
#endif
74
 
 
75
 
#ifdef WORDS_BIGENDIAN
76
 
  if (low_byte_first)
77
 
  {
78
 
    int4store(i_ptr,i_number);
 
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);
79
103
  }
80
 
  else
81
 
#endif
82
 
    longstore(i_ptr,i_number);
83
104
}
84
105
 
85
106
 
86
 
void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_number)
 
107
void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_packlength,
 
108
                  uint32_t i_number)
87
109
{
88
 
  store_length(i_ptr, i_number, getTable()->getShare()->db_low_byte_first);
 
110
  store_length(i_ptr, i_packlength, i_number, table->getShare()->db_low_byte_first);
89
111
}
90
112
 
91
113
 
92
114
uint32_t Field_blob::get_length(const unsigned char *pos,
 
115
                                uint32_t packlength_arg,
93
116
                                bool low_byte_first)
94
117
{
95
118
#ifndef WORDS_BIGENDIAN
96
119
  (void)low_byte_first;
97
120
#endif
98
 
  uint32_t tmp;
99
 
#ifdef WORDS_BIGENDIAN
100
 
  if (low_byte_first)
101
 
    tmp=uint4korr(pos);
102
 
  else
103
 
#endif
104
 
    longget(tmp,pos);
105
 
  return (uint32_t) tmp;
 
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
106
150
}
107
151
 
108
152
 
109
153
uint32_t Field_blob::get_packed_size(const unsigned char *ptr_arg,
110
154
                                bool low_byte_first)
111
155
{
112
 
  return sizeof(uint32_t) + get_length(ptr_arg, low_byte_first);
 
156
  return packlength + get_length(ptr_arg, packlength, low_byte_first);
113
157
}
114
158
 
115
159
 
116
160
uint32_t Field_blob::get_length(uint32_t row_offset)
117
161
{
118
 
  return get_length(ptr+row_offset,
119
 
                    getTable()->getShare()->db_low_byte_first);
 
162
  return get_length(ptr+row_offset, this->packlength,
 
163
                    table->getShare()->db_low_byte_first);
120
164
}
121
165
 
122
166
 
123
167
uint32_t Field_blob::get_length(const unsigned char *ptr_arg)
124
168
{
125
 
  return get_length(ptr_arg, getTable()->getShare()->db_low_byte_first);
 
169
  return get_length(ptr_arg, this->packlength, table->getShare()->db_low_byte_first);
126
170
}
127
171
 
128
172
 
129
173
/**
130
174
  Put a blob length field into a record buffer.
131
175
 
132
 
  Blob length is always stored in sizeof(uint32_t) (4 bytes)
 
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'.
133
179
 
134
180
  @param pos                 Pointer into the record buffer.
135
181
  @param length              The length value to put.
137
183
 
138
184
void Field_blob::put_length(unsigned char *pos, uint32_t length)
139
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:
140
197
    int4store(pos, length);
 
198
    break;
 
199
  }
141
200
}
142
201
 
143
202
 
160
219
 
161
220
  if (from == value.ptr())
162
221
  {
163
 
    size_t dummy_offset;
 
222
    uint32_t dummy_offset;
164
223
    if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
165
224
    {
166
225
      Field_blob::store_length(length);
167
 
      memmove(ptr+sizeof(uint32_t), &from, sizeof(char*));
 
226
      memmove(ptr+packlength, &from, sizeof(char*));
168
227
      return 0;
169
228
    }
170
229
    if (tmpstr.copy(from, length, cs))
191
250
 
192
251
  Field_blob::store_length(copy_length);
193
252
  tmp= value.ptr();
194
 
  memmove(ptr+sizeof(uint32_t), &tmp, sizeof(char*));
 
253
  memmove(ptr+packlength, &tmp, sizeof(char*));
195
254
 
196
255
  if (check_string_copy_error(this, well_formed_error_pos,
197
256
                              cannot_convert_error_pos, from + length, cs))
233
292
 
234
293
  ASSERT_COLUMN_MARKED_FOR_READ;
235
294
 
236
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
295
  memcpy(&blob,ptr+packlength,sizeof(char*));
237
296
  if (!blob)
238
297
    return 0.0;
239
298
  length= get_length(ptr);
249
308
 
250
309
  ASSERT_COLUMN_MARKED_FOR_READ;
251
310
 
252
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
311
  memcpy(&blob,ptr+packlength,sizeof(char*));
253
312
  if (!blob)
254
313
    return 0;
255
314
  uint32_t length=get_length(ptr);
263
322
 
264
323
  ASSERT_COLUMN_MARKED_FOR_READ;
265
324
 
266
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
325
  memcpy(&blob,ptr+packlength,sizeof(char*));
267
326
  if (!blob)
268
327
    val_ptr->set("",0,charset());       // A bit safer than ->length(0)
269
328
  else
272
331
}
273
332
 
274
333
 
275
 
type::Decimal *Field_blob::val_decimal(type::Decimal *decimal_value)
 
334
my_decimal *Field_blob::val_decimal(my_decimal *decimal_value)
276
335
{
277
336
  const char *blob;
278
337
  size_t length;
279
338
 
280
339
  ASSERT_COLUMN_MARKED_FOR_READ;
281
340
 
282
 
  memcpy(&blob, ptr+sizeof(uint32_t), sizeof(const unsigned char*));
 
341
  memcpy(&blob, ptr+packlength, sizeof(const unsigned char*));
283
342
  if (!blob)
284
343
  {
285
344
    blob= "";
286
345
    length= 0;
287
346
  }
288
347
  else
289
 
  {
290
348
    length= get_length(ptr);
291
 
  }
292
 
 
293
 
  decimal_value->store(E_DEC_FATAL_ERROR, blob, length, charset());
294
 
 
 
349
 
 
350
  str2my_decimal(E_DEC_FATAL_ERROR, blob, length, charset(),
 
351
                 decimal_value);
295
352
  return decimal_value;
296
353
}
297
354
 
309
366
                        uint32_t max_length)
310
367
{
311
368
  unsigned char *blob1,*blob2;
312
 
  memcpy(&blob1,a_ptr+sizeof(uint32_t),sizeof(char*));
313
 
  memcpy(&blob2,b_ptr+sizeof(uint32_t),sizeof(char*));
 
369
  memcpy(&blob1,a_ptr+packlength,sizeof(char*));
 
370
  memcpy(&blob2,b_ptr+packlength,sizeof(char*));
314
371
  uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
315
372
  set_if_smaller(a_len, max_length);
316
373
  set_if_smaller(b_len, max_length);
324
381
  char *a,*b;
325
382
  uint32_t diff;
326
383
  uint32_t a_length,b_length;
327
 
  memcpy(&a,a_ptr+sizeof(uint32_t),sizeof(char*));
328
 
  memcpy(&b,b_ptr+sizeof(uint32_t),sizeof(char*));
 
384
  memcpy(&a,a_ptr+packlength,sizeof(char*));
 
385
  memcpy(&b,b_ptr+packlength,sizeof(char*));
329
386
 
330
387
  a_length= get_length(a_ptr);
331
388
 
339
396
 
340
397
  diff= memcmp(a,b,min(a_length,b_length));
341
398
 
342
 
  return diff ? diff : (unsigned int) (a_length - b_length);
 
399
  return diff ? diff : (int) (a_length - b_length);
343
400
}
344
401
 
345
402
/* The following is used only when comparing a key */
407
464
{
408
465
  unsigned char *blob1;
409
466
  uint32_t blob_length=get_length(ptr);
410
 
  memcpy(&blob1,ptr+sizeof(uint32_t),sizeof(char*));
 
467
  memcpy(&blob1,ptr+packlength,sizeof(char*));
411
468
  const CHARSET_INFO * const cs= charset();
412
469
  uint32_t local_char_length= max_key_length / cs->mbmaxlen;
413
470
  local_char_length= my_charpos(cs, blob1, blob1+blob_length,
426
483
 
427
484
uint32_t Field_blob::sort_length() const
428
485
{
429
 
  return (uint32_t) (getTable()->getSession()->variables.max_sort_length +
430
 
                     (field_charset == &my_charset_bin ? 0 : sizeof(uint32_t)));
 
486
  return (uint32_t) (current_session->variables.max_sort_length +
 
487
                   (field_charset == &my_charset_bin ? 0 : packlength));
431
488
}
432
489
 
433
490
void Field_blob::sort_string(unsigned char *to,uint32_t length)
446
503
      /*
447
504
        Store length of blob last in blob to shorter blobs before longer blobs
448
505
      */
449
 
      length-= sizeof(uint32_t); // size of stored blob length
 
506
      length-= packlength;
450
507
      pos= to+length;
451
508
 
452
 
      mi_int4store(pos, blob_length);
 
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
      }
453
523
    }
454
 
    memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
524
    memcpy(&blob,ptr+packlength,sizeof(char*));
455
525
 
456
526
    blob_length=my_strnxfrm(field_charset,
457
527
                            to, length, blob, blob_length);
461
531
 
462
532
uint32_t Field_blob::pack_length() const
463
533
{
464
 
  return (uint32_t) (sizeof(uint32_t) + portable_sizeof_char_ptr);
 
534
  return (uint32_t) (packlength+table->getShare()->blob_ptr_size);
465
535
}
466
536
 
467
537
void Field_blob::sql_type(String &res) const
484
554
    length given is smaller than the actual length of the blob, we
485
555
    just store the initial bytes of the blob.
486
556
  */
487
 
  store_length(to, min(length, max_length), low_byte_first);
 
557
  store_length(to, packlength, min(length, max_length), low_byte_first);
488
558
 
489
559
  /*
490
560
    Store the actual blob data, which will occupy 'length' bytes.
492
562
  if (length > 0)
493
563
  {
494
564
    get_ptr((unsigned char**) &from);
495
 
    memcpy(to+sizeof(uint32_t), from,length);
 
565
    memcpy(to+packlength, from,length);
496
566
  }
497
567
 
498
568
  ptr= save;                                    // Restore org row pointer
499
 
  return(to+sizeof(uint32_t)+length);
 
569
  return(to+packlength+length);
500
570
}
501
571
 
502
572
/**
518
588
*/
519
589
const unsigned char *Field_blob::unpack(unsigned char *,
520
590
                                        const unsigned char *from,
521
 
                                        uint32_t,
 
591
                                        uint32_t param_data,
522
592
                                        bool low_byte_first)
523
593
{
524
 
  uint32_t const length= get_length(from, low_byte_first);
525
 
  getTable()->setWriteSet(position());
526
 
  store(reinterpret_cast<const char*>(from) + sizeof(uint32_t),
 
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
  table->setWriteSet(field_index);
 
598
  store(reinterpret_cast<const char*>(from) + master_packlength,
527
599
        length, field_charset);
528
 
  return(from + sizeof(uint32_t) + length);
 
600
  return(from + master_packlength + length);
529
601
}
530
602
 
531
603
/** Create a packed key that will be used for storage from a MySQL row. */
563
635
 
564
636
uint32_t Field_blob::max_display_length()
565
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:
566
647
    return (uint32_t) 4294967295U;
 
648
  default:
 
649
    assert(0); // we should never go here
 
650
    return 0;
 
651
  }
567
652
}
568
653
 
569
654
} /* namespace drizzled */