~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

  • Committer: Brian Aker
  • Date: 2008-12-16 07:07:50 UTC
  • Revision ID: brian@tangent.org-20081216070750-o5ykltxxqvn2awrx
Fixed errors test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
4
 *  Copyright (C) 2008 MySQL
18
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#ifdef USE_PRAGMA_IMPLEMENTATION
22
 
#pragma implementation                          // gcc: Class implementation
23
 
#endif
24
21
 
25
22
#include <drizzled/server_includes.h>
26
23
#include <drizzled/field/blob.h>
27
 
 
28
 
#define BLOB_PACK_LENGTH_TO_MAX_LENGH(arg) \
29
 
((uint32_t) ((1LL << min(arg, (uint)4) * 8) - 1LL))
 
24
#include <drizzled/table.h>
 
25
#include <drizzled/session.h>
 
26
 
 
27
#include <string>
 
28
 
 
29
using namespace std;
 
30
 
 
31
uint32_t
 
32
blob_pack_length_to_max_length(uint32_t arg)
 
33
{
 
34
  return (INT64_C(1) << cmin(arg, 4U) * 8) - INT64_C(1);
 
35
}
 
36
 
30
37
 
31
38
/****************************************************************************
32
39
** blob type
34
41
** packlength slot and may be from 1-4.
35
42
****************************************************************************/
36
43
 
37
 
Field_blob::Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
 
44
Field_blob::Field_blob(unsigned char *ptr_arg, unsigned char *null_ptr_arg, unsigned char null_bit_arg,
38
45
                       enum utype unireg_check_arg, const char *field_name_arg,
39
 
                       TABLE_SHARE *share, uint blob_pack_length,
 
46
                       TABLE_SHARE *share, uint32_t blob_pack_length,
40
47
                       const CHARSET_INFO * const cs)
41
 
  :Field_longstr(ptr_arg, BLOB_PACK_LENGTH_TO_MAX_LENGH(blob_pack_length),
 
48
  :Field_longstr(ptr_arg, blob_pack_length_to_max_length(blob_pack_length),
42
49
                 null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
43
50
                 cs),
44
51
   packlength(blob_pack_length)
49
56
}
50
57
 
51
58
 
52
 
void Field_blob::store_length(uchar *i_ptr,
53
 
                              uint i_packlength,
 
59
void Field_blob::store_length(unsigned char *i_ptr,
 
60
                              uint32_t i_packlength,
54
61
                              uint32_t i_number,
55
62
                              bool low_byte_first __attribute__((unused)))
56
63
{
57
64
  switch (i_packlength) {
58
65
  case 1:
59
 
    i_ptr[0]= (uchar) i_number;
 
66
    i_ptr[0]= (unsigned char) i_number;
60
67
    break;
61
68
  case 2:
62
69
#ifdef WORDS_BIGENDIAN
84
91
}
85
92
 
86
93
 
87
 
uint32_t Field_blob::get_length(const uchar *pos,
88
 
                              uint packlength_arg,
 
94
void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_packlength,
 
95
                  uint32_t i_number)
 
96
{
 
97
  store_length(i_ptr, i_packlength, i_number, table->s->db_low_byte_first);
 
98
}
 
99
 
 
100
 
 
101
uint32_t Field_blob::get_length(const unsigned char *pos,
 
102
                              uint32_t packlength_arg,
89
103
                              bool low_byte_first __attribute__((unused)))
90
104
{
91
105
  switch (packlength_arg) {
120
134
}
121
135
 
122
136
 
 
137
uint32_t Field_blob::get_packed_size(const unsigned char *ptr_arg,
 
138
                                bool low_byte_first)
 
139
{
 
140
  return packlength + get_length(ptr_arg, packlength, low_byte_first);
 
141
}
 
142
 
 
143
 
 
144
uint32_t Field_blob::get_length(uint32_t row_offset)
 
145
{
 
146
  return get_length(ptr+row_offset, this->packlength,
 
147
                    table->s->db_low_byte_first);
 
148
}
 
149
 
 
150
 
 
151
uint32_t Field_blob::get_length(const unsigned char *ptr_arg)
 
152
{
 
153
  return get_length(ptr_arg, this->packlength, table->s->db_low_byte_first);
 
154
}
 
155
 
 
156
 
123
157
/**
124
158
  Put a blob length field into a record buffer.
125
159
 
131
165
  @param length              The length value to put.
132
166
*/
133
167
 
134
 
void Field_blob::put_length(uchar *pos, uint32_t length)
 
168
void Field_blob::put_length(unsigned char *pos, uint32_t length)
135
169
{
136
170
  switch (packlength) {
137
171
  case 1:
150
184
}
151
185
 
152
186
 
153
 
int Field_blob::store(const char *from,uint length, const CHARSET_INFO * const cs)
 
187
int Field_blob::store(const char *from,uint32_t length, const CHARSET_INFO * const cs)
154
188
{
155
 
  uint copy_length, new_length;
 
189
  uint32_t copy_length, new_length;
156
190
  const char *well_formed_error_pos;
157
191
  const char *cannot_convert_error_pos;
158
192
  const char *from_end_pos, *tmp;
171
205
    if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
172
206
    {
173
207
      Field_blob::store_length(length);
174
 
      memcpy(ptr+packlength, &from, sizeof(char*));
 
208
      memmove(ptr+packlength, &from, sizeof(char*));
175
209
      return 0;
176
210
    }
177
211
    if (tmpstr.copy(from, length, cs))
179
213
    from= tmpstr.ptr();
180
214
  }
181
215
 
182
 
  new_length= min(max_data_length(), field_charset->mbmaxlen * length);
 
216
  new_length= cmin(max_data_length(), field_charset->mbmaxlen * length);
183
217
  if (value.alloc(new_length))
184
218
    goto oom_error;
185
219
 
191
225
                                            from, length);
192
226
    Field_blob::store_length(copy_length);
193
227
    tmp= value.ptr();
194
 
    memcpy(ptr + packlength, &tmp, sizeof(char*));
 
228
    memmove(ptr + packlength, &tmp, sizeof(char*));
195
229
    return 0;
196
230
  }
197
231
  /*
209
243
 
210
244
  Field_blob::store_length(copy_length);
211
245
  tmp= value.ptr();
212
 
  memcpy(ptr+packlength, &tmp, sizeof(char*));
 
246
  memmove(ptr+packlength, &tmp, sizeof(char*));
213
247
 
214
248
  if (check_string_copy_error(this, well_formed_error_pos,
215
249
                              cannot_convert_error_pos, from + length, cs))
220
254
oom_error:
221
255
  /* Fatal OOM error */
222
256
  memset(ptr, 0, Field_blob::pack_length());
223
 
  return -1; 
 
257
  return -1;
224
258
}
225
259
 
226
260
 
284
318
{
285
319
  const char *blob;
286
320
  size_t length;
287
 
  memcpy(&blob, ptr+packlength, sizeof(const uchar*));
 
321
  memcpy(&blob, ptr+packlength, sizeof(const unsigned char*));
288
322
  if (!blob)
289
323
  {
290
324
    blob= "";
299
333
}
300
334
 
301
335
 
302
 
int Field_blob::cmp(const uchar *a,uint32_t a_length, const uchar *b,
 
336
int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
303
337
                    uint32_t b_length)
304
338
{
305
 
  return field_charset->coll->strnncollsp(field_charset, 
 
339
  return field_charset->coll->strnncollsp(field_charset,
306
340
                                          a, a_length, b, b_length,
307
341
                                          0);
308
342
}
309
343
 
310
344
 
311
 
int Field_blob::cmp_max(const uchar *a_ptr, const uchar *b_ptr,
312
 
                        uint max_length)
 
345
int Field_blob::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
 
346
                        uint32_t max_length)
313
347
{
314
 
  uchar *blob1,*blob2;
 
348
  unsigned char *blob1,*blob2;
315
349
  memcpy(&blob1,a_ptr+packlength,sizeof(char*));
316
350
  memcpy(&blob2,b_ptr+packlength,sizeof(char*));
317
 
  uint a_len= get_length(a_ptr), b_len= get_length(b_ptr);
 
351
  uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
318
352
  set_if_smaller(a_len, max_length);
319
353
  set_if_smaller(b_len, max_length);
320
354
  return Field_blob::cmp(blob1,a_len,blob2,b_len);
321
355
}
322
356
 
323
357
 
324
 
int Field_blob::cmp_binary(const uchar *a_ptr, const uchar *b_ptr,
 
358
int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
325
359
                           uint32_t max_length)
326
360
{
327
361
  char *a,*b;
328
 
  uint diff;
 
362
  uint32_t diff;
329
363
  uint32_t a_length,b_length;
330
364
  memcpy(&a,a_ptr+packlength,sizeof(char*));
331
365
  memcpy(&b,b_ptr+packlength,sizeof(char*));
335
369
  b_length=get_length(b_ptr);
336
370
  if (b_length > max_length)
337
371
    b_length=max_length;
338
 
  diff=memcmp(a,b,min(a_length,b_length));
 
372
  diff=memcmp(a,b,cmin(a_length,b_length));
339
373
  return diff ? diff : (int) (a_length - b_length);
340
374
}
341
375
 
342
376
 
343
377
/* The following is used only when comparing a key */
344
378
 
345
 
uint Field_blob::get_key_image(uchar *buff,
346
 
                               uint length,
347
 
                               imagetype type_arg __attribute__((unused)))
 
379
uint32_t Field_blob::get_key_image(unsigned char *buff,
 
380
                                   uint32_t length,
 
381
                                   imagetype)
348
382
{
349
383
  uint32_t blob_length= get_length(ptr);
350
 
  uchar *blob;
 
384
  unsigned char *blob;
351
385
 
352
386
  get_ptr(&blob);
353
 
  uint local_char_length= length / field_charset->mbmaxlen;
 
387
  uint32_t local_char_length= length / field_charset->mbmaxlen;
354
388
  local_char_length= my_charpos(field_charset, blob, blob + blob_length,
355
389
                          local_char_length);
356
390
  set_if_smaller(blob_length, local_char_length);
370
404
}
371
405
 
372
406
 
373
 
void Field_blob::set_key_image(const uchar *buff,uint length)
 
407
uint32_t Field_blob::get_key_image(basic_string<unsigned char> &buff,
 
408
                                   uint32_t length,
 
409
                                   imagetype)
 
410
{
 
411
  uint32_t blob_length= get_length(ptr);
 
412
  unsigned char *blob;
 
413
 
 
414
  get_ptr(&blob);
 
415
  uint32_t local_char_length= length / field_charset->mbmaxlen;
 
416
  local_char_length= my_charpos(field_charset, blob, blob + blob_length,
 
417
                                local_char_length);
 
418
  set_if_smaller(blob_length, local_char_length);
 
419
 
 
420
  unsigned char len_buff[HA_KEY_BLOB_LENGTH];
 
421
  int2store(len_buff,length);
 
422
  buff.append(len_buff);
 
423
  buff.append(blob, blob_length);
 
424
 
 
425
  if (length > blob_length)
 
426
  {
 
427
    /*
 
428
      Must clear this as we do a memcmp in opt_range.cc to detect
 
429
      identical keys
 
430
    */
 
431
 
 
432
    buff.append(length-blob_length, '0');
 
433
  }
 
434
  return HA_KEY_BLOB_LENGTH+length;
 
435
}
 
436
 
 
437
 
 
438
void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
374
439
{
375
440
  length= uint2korr(buff);
376
441
  (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length,
378
443
}
379
444
 
380
445
 
381
 
int Field_blob::key_cmp(const uchar *key_ptr, uint max_key_length)
 
446
int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
382
447
{
383
 
  uchar *blob1;
384
 
  uint blob_length=get_length(ptr);
 
448
  unsigned char *blob1;
 
449
  uint32_t blob_length=get_length(ptr);
385
450
  memcpy(&blob1,ptr+packlength,sizeof(char*));
386
451
  const CHARSET_INFO * const cs= charset();
387
 
  uint local_char_length= max_key_length / cs->mbmaxlen;
 
452
  uint32_t local_char_length= max_key_length / cs->mbmaxlen;
388
453
  local_char_length= my_charpos(cs, blob1, blob1+blob_length,
389
454
                                local_char_length);
390
455
  set_if_smaller(blob_length, local_char_length);
393
458
                         uint2korr(key_ptr));
394
459
}
395
460
 
396
 
int Field_blob::key_cmp(const uchar *a,const uchar *b)
 
461
int Field_blob::key_cmp(const unsigned char *a,const unsigned char *b)
397
462
{
398
463
  return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
399
464
                         b+HA_KEY_BLOB_LENGTH, uint2korr(b));
410
475
 
411
476
   @returns number of bytes written to metadata_ptr
412
477
*/
413
 
int Field_blob::do_save_field_metadata(uchar *metadata_ptr)
 
478
int Field_blob::do_save_field_metadata(unsigned char *metadata_ptr)
414
479
{
415
480
  *metadata_ptr= pack_length_no_ptr();
416
481
  return 1;
419
484
 
420
485
uint32_t Field_blob::sort_length() const
421
486
{
422
 
  return (uint32_t) (current_thd->variables.max_sort_length + 
 
487
  return (uint32_t) (current_session->variables.max_sort_length +
423
488
                   (field_charset == &my_charset_bin ? 0 : packlength));
424
489
}
425
490
 
426
491
 
427
 
void Field_blob::sort_string(uchar *to,uint length)
 
492
void Field_blob::sort_string(unsigned char *to,uint32_t length)
428
493
{
429
 
  uchar *blob;
430
 
  uint blob_length=get_length();
 
494
  unsigned char *blob;
 
495
  uint32_t blob_length=get_length();
431
496
 
432
497
  if (!blob_length)
433
498
    memset(to, 0, length);
435
500
  {
436
501
    if (field_charset == &my_charset_bin)
437
502
    {
438
 
      uchar *pos;
 
503
      unsigned char *pos;
439
504
 
440
505
      /*
441
506
        Store length of blob last in blob to shorter blobs before longer blobs
459
524
      }
460
525
    }
461
526
    memcpy(&blob,ptr+packlength,sizeof(char*));
462
 
    
 
527
 
463
528
    blob_length=my_strnxfrm(field_charset,
464
529
                            to, length, blob, blob_length);
465
530
    assert(blob_length == length);
467
532
}
468
533
 
469
534
 
 
535
uint32_t Field_blob::pack_length() const
 
536
{
 
537
  return (uint32_t) (packlength+table->s->blob_ptr_size);
 
538
}
 
539
 
 
540
 
470
541
void Field_blob::sql_type(String &res) const
471
542
{
472
543
  if (charset() == &my_charset_bin)
475
546
    res.set_ascii(STRING_WITH_LEN("text"));
476
547
}
477
548
 
478
 
uchar *Field_blob::pack(uchar *to, const uchar *from,
479
 
                        uint max_length, bool low_byte_first)
 
549
unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
 
550
                        uint32_t max_length, bool low_byte_first)
480
551
{
481
 
  uchar *save= ptr;
482
 
  ptr= (uchar*) from;
 
552
  unsigned char *save= ptr;
 
553
  ptr= (unsigned char*) from;
483
554
  uint32_t length=get_length();                 // Length of from string
484
555
 
485
556
  /*
487
558
    length given is smaller than the actual length of the blob, we
488
559
    just store the initial bytes of the blob.
489
560
  */
490
 
  store_length(to, packlength, min(length, max_length), low_byte_first);
 
561
  store_length(to, packlength, cmin(length, max_length), low_byte_first);
491
562
 
492
563
  /*
493
564
    Store the actual blob data, which will occupy 'length' bytes.
494
565
   */
495
566
  if (length > 0)
496
567
  {
497
 
    get_ptr((uchar**) &from);
 
568
    get_ptr((unsigned char**) &from);
498
569
    memcpy(to+packlength, from,length);
499
570
  }
500
571
  ptr=save;                                     // Restore org row pointer
505
576
/**
506
577
   Unpack a blob field from row data.
507
578
 
508
 
   This method is used to unpack a blob field from a master whose size of 
 
579
   This method is used to unpack a blob field from a master whose size of
509
580
   the field is less than that of the slave. Note: This method is included
510
581
   to satisfy inheritance rules, but is not needed for blob fields. It
511
582
   simply is used as a pass-through to the original unpack() method for
519
590
 
520
591
   @return  New pointer into memory based on from + length of the data
521
592
*/
522
 
const uchar *Field_blob::unpack(uchar *to __attribute__((unused)),
523
 
                                const uchar *from,
524
 
                                uint param_data,
 
593
const unsigned char *Field_blob::unpack(unsigned char *to __attribute__((unused)),
 
594
                                const unsigned char *from,
 
595
                                uint32_t param_data,
525
596
                                bool low_byte_first)
526
597
{
527
 
  uint const master_packlength=
 
598
  uint32_t const master_packlength=
528
599
    param_data > 0 ? param_data & 0xFF : packlength;
529
600
  uint32_t const length= get_length(from, master_packlength, low_byte_first);
530
601
  bitmap_set_bit(table->write_set, field_index);
535
606
 
536
607
/* Keys for blobs are like keys on varchars */
537
608
 
538
 
int Field_blob::pack_cmp(const uchar *a, const uchar *b, uint key_length_arg,
 
609
int Field_blob::pack_cmp(const unsigned char *a, const unsigned char *b, uint32_t key_length_arg,
539
610
                         bool insert_or_update)
540
611
{
541
 
  uint a_length, b_length;
 
612
  uint32_t a_length, b_length;
542
613
  if (key_length_arg > 255)
543
614
  {
544
615
    a_length=uint2korr(a); a+=2;
556
627
}
557
628
 
558
629
 
559
 
int Field_blob::pack_cmp(const uchar *b, uint key_length_arg,
 
630
int Field_blob::pack_cmp(const unsigned char *b, uint32_t key_length_arg,
560
631
                         bool insert_or_update)
561
632
{
562
 
  uchar *a;
563
 
  uint a_length, b_length;
 
633
  unsigned char *a;
 
634
  uint32_t a_length, b_length;
564
635
  memcpy(&a,ptr+packlength,sizeof(char*));
565
636
  if (!a)
566
637
    return key_length_arg > 0 ? -1 : 0;
580
651
 
581
652
/** Create a packed key that will be used for storage from a MySQL row. */
582
653
 
583
 
uchar *
584
 
Field_blob::pack_key(uchar *to, const uchar *from, uint max_length,
 
654
unsigned char *
 
655
Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
585
656
                     bool low_byte_first __attribute__((unused)))
586
657
{
587
 
  uchar *save= ptr;
588
 
  ptr= (uchar*) from;
 
658
  unsigned char *save= ptr;
 
659
  ptr= (unsigned char*) from;
589
660
  uint32_t length=get_length();        // Length of from string
590
 
  uint local_char_length= ((field_charset->mbmaxlen > 1) ?
 
661
  uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
591
662
                           max_length/field_charset->mbmaxlen : max_length);
592
663
  if (length)
593
 
    get_ptr((uchar**) &from);
 
664
    get_ptr((unsigned char**) &from);
594
665
  if (length > local_char_length)
595
666
    local_char_length= my_charpos(field_charset, from, from+length,
596
667
                                  local_char_length);
597
668
  set_if_smaller(length, local_char_length);
598
 
  *to++= (uchar) length;
 
669
  *to++= (unsigned char) length;
599
670
  if (max_length > 255)                         // 2 byte length
600
 
    *to++= (uchar) (length >> 8);
 
671
    *to++= (unsigned char) (length >> 8);
601
672
  memcpy(to, from, length);
602
673
  ptr=save;                                     // Restore org row pointer
603
674
  return to+length;
625
696
    Pointer into 'from' past the last byte copied from packed key.
626
697
*/
627
698
 
628
 
const uchar *
629
 
Field_blob::unpack_key(uchar *to, const uchar *from, uint max_length,
 
699
const unsigned char *
 
700
Field_blob::unpack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
630
701
                       bool low_byte_first __attribute__((unused)))
631
702
{
632
703
  /* get length of the blob key */
650
721
 
651
722
/** Create a packed key that will be used for storage from a MySQL key. */
652
723
 
653
 
uchar *
654
 
Field_blob::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length,
 
724
unsigned char *
 
725
Field_blob::pack_key_from_key_image(unsigned char *to, const unsigned char *from, uint32_t max_length,
655
726
                                    bool low_byte_first __attribute__((unused)))
656
727
{
657
 
  uint length=uint2korr(from);
 
728
  uint32_t length=uint2korr(from);
658
729
  if (length > max_length)
659
730
    length=max_length;
660
731
  *to++= (char) (length & 255);
666
737
}
667
738
 
668
739
 
669
 
uint Field_blob::packed_col_length(const uchar *data_ptr, uint length)
 
740
uint32_t Field_blob::packed_col_length(const unsigned char *data_ptr, uint32_t length)
670
741
{
671
742
  if (length > 255)
672
743
    return uint2korr(data_ptr)+2;
674
745
}
675
746
 
676
747
 
677
 
uint Field_blob::max_packed_col_length(uint max_length)
 
748
uint32_t Field_blob::max_packed_col_length(uint32_t max_length)
678
749
{
679
750
  return (max_length > 255 ? 2 : 1)+max_length;
680
751
}
681
752
 
682
753
 
683
 
uint Field_blob::is_equal(Create_field *new_field)
 
754
uint32_t Field_blob::is_equal(Create_field *new_field)
684
755
{
685
756
  if (compare_str_field_flags(new_field, flags))
686
757
    return 0;
717
788
  }
718
789
}
719
790
 
 
791
bool Field_blob::in_read_set()
 
792
{
 
793
  return bitmap_is_set(table->read_set, field_index);
 
794
}
 
795
 
 
796
 
 
797
bool Field_blob::in_write_set()
 
798
{
 
799
  return bitmap_is_set(table->write_set, field_index);
 
800
}