~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

  • Committer: Brian Aker
  • Date: 2010-02-03 21:54:38 UTC
  • mto: This revision was merged to the branch mainline in revision 1281.
  • Revision ID: brian@gaz-20100203215438-9ixkp214vio85mub
Fixing test cases/removed dead optimizer switches.

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
 
31
31
using namespace std;
32
32
 
33
 
namespace drizzled
34
 
{
35
 
 
36
33
static uint32_t blob_pack_length_to_max_length(uint32_t arg)
37
34
{
38
35
  return max(UINT32_MAX,
43
40
/****************************************************************************
44
41
** blob type
45
42
** 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)
 
43
** packlength slot and may be from 1-4.
47
44
****************************************************************************/
48
45
 
49
46
Field_blob::Field_blob(unsigned char *ptr_arg,
51
48
                       unsigned char null_bit_arg,
52
49
                                   const char *field_name_arg,
53
50
                       TableShare *share,
 
51
                       uint32_t blob_pack_length,
54
52
                       const CHARSET_INFO * const cs)
55
53
  :Field_str(ptr_arg,
56
 
             blob_pack_length_to_max_length(sizeof(uint32_t)),
 
54
             blob_pack_length_to_max_length(blob_pack_length),
57
55
             null_ptr_arg,
58
56
             null_bit_arg,
59
57
             field_name_arg,
60
 
             cs)
 
58
             cs),
 
59
   packlength(blob_pack_length)
61
60
{
62
61
  flags|= BLOB_FLAG;
63
62
  share->blob_fields++;
64
 
  /* TODO: why do not fill table->getShare()->blob_field array here? */
 
63
  /* TODO: why do not fill table->s->blob_field array here? */
65
64
}
66
65
 
67
66
void Field_blob::store_length(unsigned char *i_ptr,
 
67
                              uint32_t i_packlength,
68
68
                              uint32_t i_number,
69
69
                              bool low_byte_first)
70
70
{
71
71
#ifndef WORDS_BIGENDIAN
72
72
  (void)low_byte_first;
73
73
#endif
74
 
 
75
 
#ifdef WORDS_BIGENDIAN
76
 
  if (low_byte_first)
77
 
  {
78
 
    int4store(i_ptr,i_number);
 
74
  switch (i_packlength) {
 
75
  case 1:
 
76
    i_ptr[0]= (unsigned char) i_number;
 
77
    break;
 
78
  case 2:
 
79
#ifdef WORDS_BIGENDIAN
 
80
    if (low_byte_first)
 
81
    {
 
82
      int2store(i_ptr,(unsigned short) i_number);
 
83
    }
 
84
    else
 
85
#endif
 
86
      shortstore(i_ptr,(unsigned short) i_number);
 
87
    break;
 
88
  case 3:
 
89
    int3store(i_ptr,i_number);
 
90
    break;
 
91
  case 4:
 
92
#ifdef WORDS_BIGENDIAN
 
93
    if (low_byte_first)
 
94
    {
 
95
      int4store(i_ptr,i_number);
 
96
    }
 
97
    else
 
98
#endif
 
99
      longstore(i_ptr,i_number);
79
100
  }
80
 
  else
81
 
#endif
82
 
    longstore(i_ptr,i_number);
83
101
}
84
102
 
85
103
 
86
 
void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_number)
 
104
void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_packlength,
 
105
                  uint32_t i_number)
87
106
{
88
 
  store_length(i_ptr, i_number, getTable()->getShare()->db_low_byte_first);
 
107
  store_length(i_ptr, i_packlength, i_number, table->s->db_low_byte_first);
89
108
}
90
109
 
91
110
 
92
111
uint32_t Field_blob::get_length(const unsigned char *pos,
 
112
                                uint32_t packlength_arg,
93
113
                                bool low_byte_first)
94
114
{
95
115
#ifndef WORDS_BIGENDIAN
96
116
  (void)low_byte_first;
97
117
#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;
 
118
  switch (packlength_arg) {
 
119
  case 1:
 
120
    return (uint32_t) pos[0];
 
121
  case 2:
 
122
    {
 
123
      uint16_t tmp;
 
124
#ifdef WORDS_BIGENDIAN
 
125
      if (low_byte_first)
 
126
        tmp=sint2korr(pos);
 
127
      else
 
128
#endif
 
129
        shortget(tmp,pos);
 
130
      return (uint32_t) tmp;
 
131
    }
 
132
  case 3:
 
133
    return (uint32_t) uint3korr(pos);
 
134
  case 4:
 
135
    {
 
136
      uint32_t tmp;
 
137
#ifdef WORDS_BIGENDIAN
 
138
      if (low_byte_first)
 
139
        tmp=uint4korr(pos);
 
140
      else
 
141
#endif
 
142
        longget(tmp,pos);
 
143
      return (uint32_t) tmp;
 
144
    }
 
145
  }
 
146
  return 0;                                     // Impossible
106
147
}
107
148
 
108
149
 
109
150
uint32_t Field_blob::get_packed_size(const unsigned char *ptr_arg,
110
151
                                bool low_byte_first)
111
152
{
112
 
  return sizeof(uint32_t) + get_length(ptr_arg, low_byte_first);
 
153
  return packlength + get_length(ptr_arg, packlength, low_byte_first);
113
154
}
114
155
 
115
156
 
116
157
uint32_t Field_blob::get_length(uint32_t row_offset)
117
158
{
118
 
  return get_length(ptr+row_offset,
119
 
                    getTable()->getShare()->db_low_byte_first);
 
159
  return get_length(ptr+row_offset, this->packlength,
 
160
                    table->s->db_low_byte_first);
120
161
}
121
162
 
122
163
 
123
164
uint32_t Field_blob::get_length(const unsigned char *ptr_arg)
124
165
{
125
 
  return get_length(ptr_arg, getTable()->getShare()->db_low_byte_first);
 
166
  return get_length(ptr_arg, this->packlength, table->s->db_low_byte_first);
126
167
}
127
168
 
128
169
 
129
170
/**
130
171
  Put a blob length field into a record buffer.
131
172
 
132
 
  Blob length is always stored in sizeof(uint32_t) (4 bytes)
 
173
  Depending on the maximum length of a blob, its length field is
 
174
  put into 1 to 4 bytes. This is a property of the blob object,
 
175
  described by 'packlength'.
133
176
 
134
177
  @param pos                 Pointer into the record buffer.
135
178
  @param length              The length value to put.
137
180
 
138
181
void Field_blob::put_length(unsigned char *pos, uint32_t length)
139
182
{
 
183
  switch (packlength) {
 
184
  case 1:
 
185
    *pos= (char) length;
 
186
    break;
 
187
  case 2:
 
188
    int2store(pos, length);
 
189
    break;
 
190
  case 3:
 
191
    int3store(pos, length);
 
192
    break;
 
193
  case 4:
140
194
    int4store(pos, length);
 
195
    break;
 
196
  }
141
197
}
142
198
 
143
199
 
160
216
 
161
217
  if (from == value.ptr())
162
218
  {
163
 
    size_t dummy_offset;
 
219
    uint32_t dummy_offset;
164
220
    if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
165
221
    {
166
222
      Field_blob::store_length(length);
167
 
      memmove(ptr+sizeof(uint32_t), &from, sizeof(char*));
 
223
      memmove(ptr+packlength, &from, sizeof(char*));
168
224
      return 0;
169
225
    }
170
226
    if (tmpstr.copy(from, length, cs))
191
247
 
192
248
  Field_blob::store_length(copy_length);
193
249
  tmp= value.ptr();
194
 
  memmove(ptr+sizeof(uint32_t), &tmp, sizeof(char*));
 
250
  memmove(ptr+packlength, &tmp, sizeof(char*));
195
251
 
196
252
  if (check_string_copy_error(this, well_formed_error_pos,
197
253
                              cannot_convert_error_pos, from + length, cs))
233
289
 
234
290
  ASSERT_COLUMN_MARKED_FOR_READ;
235
291
 
236
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
292
  memcpy(&blob,ptr+packlength,sizeof(char*));
237
293
  if (!blob)
238
294
    return 0.0;
239
295
  length= get_length(ptr);
249
305
 
250
306
  ASSERT_COLUMN_MARKED_FOR_READ;
251
307
 
252
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
308
  memcpy(&blob,ptr+packlength,sizeof(char*));
253
309
  if (!blob)
254
310
    return 0;
255
311
  uint32_t length=get_length(ptr);
263
319
 
264
320
  ASSERT_COLUMN_MARKED_FOR_READ;
265
321
 
266
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
322
  memcpy(&blob,ptr+packlength,sizeof(char*));
267
323
  if (!blob)
268
324
    val_ptr->set("",0,charset());       // A bit safer than ->length(0)
269
325
  else
279
335
 
280
336
  ASSERT_COLUMN_MARKED_FOR_READ;
281
337
 
282
 
  memcpy(&blob, ptr+sizeof(uint32_t), sizeof(const unsigned char*));
 
338
  memcpy(&blob, ptr+packlength, sizeof(const unsigned char*));
283
339
  if (!blob)
284
340
  {
285
341
    blob= "";
307
363
                        uint32_t max_length)
308
364
{
309
365
  unsigned char *blob1,*blob2;
310
 
  memcpy(&blob1,a_ptr+sizeof(uint32_t),sizeof(char*));
311
 
  memcpy(&blob2,b_ptr+sizeof(uint32_t),sizeof(char*));
 
366
  memcpy(&blob1,a_ptr+packlength,sizeof(char*));
 
367
  memcpy(&blob2,b_ptr+packlength,sizeof(char*));
312
368
  uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
313
369
  set_if_smaller(a_len, max_length);
314
370
  set_if_smaller(b_len, max_length);
322
378
  char *a,*b;
323
379
  uint32_t diff;
324
380
  uint32_t a_length,b_length;
325
 
  memcpy(&a,a_ptr+sizeof(uint32_t),sizeof(char*));
326
 
  memcpy(&b,b_ptr+sizeof(uint32_t),sizeof(char*));
 
381
  memcpy(&a,a_ptr+packlength,sizeof(char*));
 
382
  memcpy(&b,b_ptr+packlength,sizeof(char*));
327
383
 
328
384
  a_length= get_length(a_ptr);
329
385
 
337
393
 
338
394
  diff= memcmp(a,b,min(a_length,b_length));
339
395
 
340
 
  return diff ? diff : (unsigned int) (a_length - b_length);
 
396
  return diff ? diff : (int) (a_length - b_length);
341
397
}
342
398
 
343
399
/* The following is used only when comparing a key */
405
461
{
406
462
  unsigned char *blob1;
407
463
  uint32_t blob_length=get_length(ptr);
408
 
  memcpy(&blob1,ptr+sizeof(uint32_t),sizeof(char*));
 
464
  memcpy(&blob1,ptr+packlength,sizeof(char*));
409
465
  const CHARSET_INFO * const cs= charset();
410
466
  uint32_t local_char_length= max_key_length / cs->mbmaxlen;
411
467
  local_char_length= my_charpos(cs, blob1, blob1+blob_length,
425
481
uint32_t Field_blob::sort_length() const
426
482
{
427
483
  return (uint32_t) (current_session->variables.max_sort_length +
428
 
                     (field_charset == &my_charset_bin ? 0 : sizeof(uint32_t)));
 
484
                   (field_charset == &my_charset_bin ? 0 : packlength));
429
485
}
430
486
 
431
487
void Field_blob::sort_string(unsigned char *to,uint32_t length)
444
500
      /*
445
501
        Store length of blob last in blob to shorter blobs before longer blobs
446
502
      */
447
 
      length-= sizeof(uint32_t); // size of stored blob length
 
503
      length-= packlength;
448
504
      pos= to+length;
449
505
 
450
 
      mi_int4store(pos, blob_length);
 
506
      switch (packlength) {
 
507
      case 1:
 
508
        *pos= (char) blob_length;
 
509
        break;
 
510
      case 2:
 
511
        mi_int2store(pos, blob_length);
 
512
        break;
 
513
      case 3:
 
514
        mi_int3store(pos, blob_length);
 
515
        break;
 
516
      case 4:
 
517
        mi_int4store(pos, blob_length);
 
518
        break;
 
519
      }
451
520
    }
452
 
    memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
521
    memcpy(&blob,ptr+packlength,sizeof(char*));
453
522
 
454
523
    blob_length=my_strnxfrm(field_charset,
455
524
                            to, length, blob, blob_length);
459
528
 
460
529
uint32_t Field_blob::pack_length() const
461
530
{
462
 
  return (uint32_t) (sizeof(uint32_t) + portable_sizeof_char_ptr);
 
531
  return (uint32_t) (packlength+table->s->blob_ptr_size);
463
532
}
464
533
 
465
534
void Field_blob::sql_type(String &res) const
482
551
    length given is smaller than the actual length of the blob, we
483
552
    just store the initial bytes of the blob.
484
553
  */
485
 
  store_length(to, min(length, max_length), low_byte_first);
 
554
  store_length(to, packlength, min(length, max_length), low_byte_first);
486
555
 
487
556
  /*
488
557
    Store the actual blob data, which will occupy 'length' bytes.
490
559
  if (length > 0)
491
560
  {
492
561
    get_ptr((unsigned char**) &from);
493
 
    memcpy(to+sizeof(uint32_t), from,length);
 
562
    memcpy(to+packlength, from,length);
494
563
  }
495
564
 
496
565
  ptr= save;                                    // Restore org row pointer
497
 
  return(to+sizeof(uint32_t)+length);
 
566
  return(to+packlength+length);
498
567
}
499
568
 
500
569
/**
516
585
*/
517
586
const unsigned char *Field_blob::unpack(unsigned char *,
518
587
                                        const unsigned char *from,
519
 
                                        uint32_t,
 
588
                                        uint32_t param_data,
520
589
                                        bool low_byte_first)
521
590
{
522
 
  uint32_t const length= get_length(from, low_byte_first);
523
 
  getTable()->setWriteSet(position());
524
 
  store(reinterpret_cast<const char*>(from) + sizeof(uint32_t),
 
591
  uint32_t const master_packlength=
 
592
    param_data > 0 ? param_data & 0xFF : packlength;
 
593
  uint32_t const length= get_length(from, master_packlength, low_byte_first);
 
594
  table->setWriteSet(field_index);
 
595
  store(reinterpret_cast<const char*>(from) + master_packlength,
525
596
        length, field_charset);
526
 
  return(from + sizeof(uint32_t) + length);
 
597
  return(from + master_packlength + length);
527
598
}
528
599
 
529
600
/** Create a packed key that will be used for storage from a MySQL row. */
561
632
 
562
633
uint32_t Field_blob::max_display_length()
563
634
{
 
635
  switch (packlength)
 
636
  {
 
637
  case 1:
 
638
    return 255 * field_charset->mbmaxlen;
 
639
  case 2:
 
640
    return 65535 * field_charset->mbmaxlen;
 
641
  case 3:
 
642
    return 16777215 * field_charset->mbmaxlen;
 
643
  case 4:
564
644
    return (uint32_t) 4294967295U;
 
645
  default:
 
646
    assert(0); // we should never go here
 
647
    return 0;
 
648
  }
565
649
}
566
 
 
567
 
} /* namespace drizzled */