~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

Much closer toward UTF8 being around all the time...

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
21
24
 
22
25
#include <drizzled/server_includes.h>
23
26
#include <drizzled/field/blob.h>
24
27
 
25
28
uint32_t
26
 
blob_pack_length_to_max_length(uint32_t arg)
 
29
blob_pack_length_to_max_length(uint arg)
27
30
{
28
 
  return (INT64_C(1) << cmin(arg, 4U) * 8) - INT64_C(1);
 
31
  return (1LL << min(arg, 4U) * 8) - 1LL;
29
32
}
30
33
 
31
34
 
35
38
** packlength slot and may be from 1-4.
36
39
****************************************************************************/
37
40
 
38
 
Field_blob::Field_blob(unsigned char *ptr_arg, unsigned char *null_ptr_arg, unsigned char null_bit_arg,
 
41
Field_blob::Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
39
42
                       enum utype unireg_check_arg, const char *field_name_arg,
40
 
                       TABLE_SHARE *share, uint32_t blob_pack_length,
 
43
                       TABLE_SHARE *share, uint blob_pack_length,
41
44
                       const CHARSET_INFO * const cs)
42
45
  :Field_longstr(ptr_arg, blob_pack_length_to_max_length(blob_pack_length),
43
46
                 null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
50
53
}
51
54
 
52
55
 
53
 
void Field_blob::store_length(unsigned char *i_ptr,
54
 
                              uint32_t i_packlength,
 
56
void Field_blob::store_length(uchar *i_ptr,
 
57
                              uint i_packlength,
55
58
                              uint32_t i_number,
56
59
                              bool low_byte_first __attribute__((unused)))
57
60
{
58
61
  switch (i_packlength) {
59
62
  case 1:
60
 
    i_ptr[0]= (unsigned char) i_number;
 
63
    i_ptr[0]= (uchar) i_number;
61
64
    break;
62
65
  case 2:
63
66
#ifdef WORDS_BIGENDIAN
85
88
}
86
89
 
87
90
 
88
 
uint32_t Field_blob::get_length(const unsigned char *pos,
89
 
                              uint32_t packlength_arg,
 
91
uint32_t Field_blob::get_length(const uchar *pos,
 
92
                              uint packlength_arg,
90
93
                              bool low_byte_first __attribute__((unused)))
91
94
{
92
95
  switch (packlength_arg) {
132
135
  @param length              The length value to put.
133
136
*/
134
137
 
135
 
void Field_blob::put_length(unsigned char *pos, uint32_t length)
 
138
void Field_blob::put_length(uchar *pos, uint32_t length)
136
139
{
137
140
  switch (packlength) {
138
141
  case 1:
151
154
}
152
155
 
153
156
 
154
 
int Field_blob::store(const char *from,uint32_t length, const CHARSET_INFO * const cs)
 
157
int Field_blob::store(const char *from,uint length, const CHARSET_INFO * const cs)
155
158
{
156
 
  uint32_t copy_length, new_length;
 
159
  uint copy_length, new_length;
157
160
  const char *well_formed_error_pos;
158
161
  const char *cannot_convert_error_pos;
159
162
  const char *from_end_pos, *tmp;
180
183
    from= tmpstr.ptr();
181
184
  }
182
185
 
183
 
  new_length= cmin(max_data_length(), field_charset->mbmaxlen * length);
 
186
  new_length= min(max_data_length(), field_charset->mbmaxlen * length);
184
187
  if (value.alloc(new_length))
185
188
    goto oom_error;
186
189
 
285
288
{
286
289
  const char *blob;
287
290
  size_t length;
288
 
  memcpy(&blob, ptr+packlength, sizeof(const unsigned char*));
 
291
  memcpy(&blob, ptr+packlength, sizeof(const uchar*));
289
292
  if (!blob)
290
293
  {
291
294
    blob= "";
300
303
}
301
304
 
302
305
 
303
 
int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
 
306
int Field_blob::cmp(const uchar *a,uint32_t a_length, const uchar *b,
304
307
                    uint32_t b_length)
305
308
{
306
309
  return field_charset->coll->strnncollsp(field_charset, 
309
312
}
310
313
 
311
314
 
312
 
int Field_blob::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
313
 
                        uint32_t max_length)
 
315
int Field_blob::cmp_max(const uchar *a_ptr, const uchar *b_ptr,
 
316
                        uint max_length)
314
317
{
315
 
  unsigned char *blob1,*blob2;
 
318
  uchar *blob1,*blob2;
316
319
  memcpy(&blob1,a_ptr+packlength,sizeof(char*));
317
320
  memcpy(&blob2,b_ptr+packlength,sizeof(char*));
318
 
  uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
 
321
  uint a_len= get_length(a_ptr), b_len= get_length(b_ptr);
319
322
  set_if_smaller(a_len, max_length);
320
323
  set_if_smaller(b_len, max_length);
321
324
  return Field_blob::cmp(blob1,a_len,blob2,b_len);
322
325
}
323
326
 
324
327
 
325
 
int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
 
328
int Field_blob::cmp_binary(const uchar *a_ptr, const uchar *b_ptr,
326
329
                           uint32_t max_length)
327
330
{
328
331
  char *a,*b;
329
 
  uint32_t diff;
 
332
  uint diff;
330
333
  uint32_t a_length,b_length;
331
334
  memcpy(&a,a_ptr+packlength,sizeof(char*));
332
335
  memcpy(&b,b_ptr+packlength,sizeof(char*));
336
339
  b_length=get_length(b_ptr);
337
340
  if (b_length > max_length)
338
341
    b_length=max_length;
339
 
  diff=memcmp(a,b,cmin(a_length,b_length));
 
342
  diff=memcmp(a,b,min(a_length,b_length));
340
343
  return diff ? diff : (int) (a_length - b_length);
341
344
}
342
345
 
343
346
 
344
347
/* The following is used only when comparing a key */
345
348
 
346
 
uint32_t Field_blob::get_key_image(unsigned char *buff,
347
 
                               uint32_t length,
 
349
uint Field_blob::get_key_image(uchar *buff,
 
350
                               uint length,
348
351
                               imagetype type_arg __attribute__((unused)))
349
352
{
350
353
  uint32_t blob_length= get_length(ptr);
351
 
  unsigned char *blob;
 
354
  uchar *blob;
352
355
 
353
356
  get_ptr(&blob);
354
 
  uint32_t local_char_length= length / field_charset->mbmaxlen;
 
357
  uint local_char_length= length / field_charset->mbmaxlen;
355
358
  local_char_length= my_charpos(field_charset, blob, blob + blob_length,
356
359
                          local_char_length);
357
360
  set_if_smaller(blob_length, local_char_length);
371
374
}
372
375
 
373
376
 
374
 
void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
 
377
void Field_blob::set_key_image(const uchar *buff,uint length)
375
378
{
376
379
  length= uint2korr(buff);
377
380
  (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length,
379
382
}
380
383
 
381
384
 
382
 
int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
 
385
int Field_blob::key_cmp(const uchar *key_ptr, uint max_key_length)
383
386
{
384
 
  unsigned char *blob1;
385
 
  uint32_t blob_length=get_length(ptr);
 
387
  uchar *blob1;
 
388
  uint blob_length=get_length(ptr);
386
389
  memcpy(&blob1,ptr+packlength,sizeof(char*));
387
390
  const CHARSET_INFO * const cs= charset();
388
 
  uint32_t local_char_length= max_key_length / cs->mbmaxlen;
 
391
  uint local_char_length= max_key_length / cs->mbmaxlen;
389
392
  local_char_length= my_charpos(cs, blob1, blob1+blob_length,
390
393
                                local_char_length);
391
394
  set_if_smaller(blob_length, local_char_length);
394
397
                         uint2korr(key_ptr));
395
398
}
396
399
 
397
 
int Field_blob::key_cmp(const unsigned char *a,const unsigned char *b)
 
400
int Field_blob::key_cmp(const uchar *a,const uchar *b)
398
401
{
399
402
  return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
400
403
                         b+HA_KEY_BLOB_LENGTH, uint2korr(b));
411
414
 
412
415
   @returns number of bytes written to metadata_ptr
413
416
*/
414
 
int Field_blob::do_save_field_metadata(unsigned char *metadata_ptr)
 
417
int Field_blob::do_save_field_metadata(uchar *metadata_ptr)
415
418
{
416
419
  *metadata_ptr= pack_length_no_ptr();
417
420
  return 1;
425
428
}
426
429
 
427
430
 
428
 
void Field_blob::sort_string(unsigned char *to,uint32_t length)
 
431
void Field_blob::sort_string(uchar *to,uint length)
429
432
{
430
 
  unsigned char *blob;
431
 
  uint32_t blob_length=get_length();
 
433
  uchar *blob;
 
434
  uint blob_length=get_length();
432
435
 
433
436
  if (!blob_length)
434
437
    memset(to, 0, length);
436
439
  {
437
440
    if (field_charset == &my_charset_bin)
438
441
    {
439
 
      unsigned char *pos;
 
442
      uchar *pos;
440
443
 
441
444
      /*
442
445
        Store length of blob last in blob to shorter blobs before longer blobs
476
479
    res.set_ascii(STRING_WITH_LEN("text"));
477
480
}
478
481
 
479
 
unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
480
 
                        uint32_t max_length, bool low_byte_first)
 
482
uchar *Field_blob::pack(uchar *to, const uchar *from,
 
483
                        uint max_length, bool low_byte_first)
481
484
{
482
 
  unsigned char *save= ptr;
483
 
  ptr= (unsigned char*) from;
 
485
  uchar *save= ptr;
 
486
  ptr= (uchar*) from;
484
487
  uint32_t length=get_length();                 // Length of from string
485
488
 
486
489
  /*
488
491
    length given is smaller than the actual length of the blob, we
489
492
    just store the initial bytes of the blob.
490
493
  */
491
 
  store_length(to, packlength, cmin(length, max_length), low_byte_first);
 
494
  store_length(to, packlength, min(length, max_length), low_byte_first);
492
495
 
493
496
  /*
494
497
    Store the actual blob data, which will occupy 'length' bytes.
495
498
   */
496
499
  if (length > 0)
497
500
  {
498
 
    get_ptr((unsigned char**) &from);
 
501
    get_ptr((uchar**) &from);
499
502
    memcpy(to+packlength, from,length);
500
503
  }
501
504
  ptr=save;                                     // Restore org row pointer
520
523
 
521
524
   @return  New pointer into memory based on from + length of the data
522
525
*/
523
 
const unsigned char *Field_blob::unpack(unsigned char *to __attribute__((unused)),
524
 
                                const unsigned char *from,
525
 
                                uint32_t param_data,
 
526
const uchar *Field_blob::unpack(uchar *to __attribute__((unused)),
 
527
                                const uchar *from,
 
528
                                uint param_data,
526
529
                                bool low_byte_first)
527
530
{
528
 
  uint32_t const master_packlength=
 
531
  uint const master_packlength=
529
532
    param_data > 0 ? param_data & 0xFF : packlength;
530
533
  uint32_t const length= get_length(from, master_packlength, low_byte_first);
531
534
  bitmap_set_bit(table->write_set, field_index);
536
539
 
537
540
/* Keys for blobs are like keys on varchars */
538
541
 
539
 
int Field_blob::pack_cmp(const unsigned char *a, const unsigned char *b, uint32_t key_length_arg,
 
542
int Field_blob::pack_cmp(const uchar *a, const uchar *b, uint key_length_arg,
540
543
                         bool insert_or_update)
541
544
{
542
 
  uint32_t a_length, b_length;
 
545
  uint a_length, b_length;
543
546
  if (key_length_arg > 255)
544
547
  {
545
548
    a_length=uint2korr(a); a+=2;
557
560
}
558
561
 
559
562
 
560
 
int Field_blob::pack_cmp(const unsigned char *b, uint32_t key_length_arg,
 
563
int Field_blob::pack_cmp(const uchar *b, uint key_length_arg,
561
564
                         bool insert_or_update)
562
565
{
563
 
  unsigned char *a;
564
 
  uint32_t a_length, b_length;
 
566
  uchar *a;
 
567
  uint a_length, b_length;
565
568
  memcpy(&a,ptr+packlength,sizeof(char*));
566
569
  if (!a)
567
570
    return key_length_arg > 0 ? -1 : 0;
581
584
 
582
585
/** Create a packed key that will be used for storage from a MySQL row. */
583
586
 
584
 
unsigned char *
585
 
Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
 
587
uchar *
 
588
Field_blob::pack_key(uchar *to, const uchar *from, uint max_length,
586
589
                     bool low_byte_first __attribute__((unused)))
587
590
{
588
 
  unsigned char *save= ptr;
589
 
  ptr= (unsigned char*) from;
 
591
  uchar *save= ptr;
 
592
  ptr= (uchar*) from;
590
593
  uint32_t length=get_length();        // Length of from string
591
 
  uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
 
594
  uint local_char_length= ((field_charset->mbmaxlen > 1) ?
592
595
                           max_length/field_charset->mbmaxlen : max_length);
593
596
  if (length)
594
 
    get_ptr((unsigned char**) &from);
 
597
    get_ptr((uchar**) &from);
595
598
  if (length > local_char_length)
596
599
    local_char_length= my_charpos(field_charset, from, from+length,
597
600
                                  local_char_length);
598
601
  set_if_smaller(length, local_char_length);
599
 
  *to++= (unsigned char) length;
 
602
  *to++= (uchar) length;
600
603
  if (max_length > 255)                         // 2 byte length
601
 
    *to++= (unsigned char) (length >> 8);
 
604
    *to++= (uchar) (length >> 8);
602
605
  memcpy(to, from, length);
603
606
  ptr=save;                                     // Restore org row pointer
604
607
  return to+length;
626
629
    Pointer into 'from' past the last byte copied from packed key.
627
630
*/
628
631
 
629
 
const unsigned char *
630
 
Field_blob::unpack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
 
632
const uchar *
 
633
Field_blob::unpack_key(uchar *to, const uchar *from, uint max_length,
631
634
                       bool low_byte_first __attribute__((unused)))
632
635
{
633
636
  /* get length of the blob key */
651
654
 
652
655
/** Create a packed key that will be used for storage from a MySQL key. */
653
656
 
654
 
unsigned char *
655
 
Field_blob::pack_key_from_key_image(unsigned char *to, const unsigned char *from, uint32_t max_length,
 
657
uchar *
 
658
Field_blob::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length,
656
659
                                    bool low_byte_first __attribute__((unused)))
657
660
{
658
 
  uint32_t length=uint2korr(from);
 
661
  uint length=uint2korr(from);
659
662
  if (length > max_length)
660
663
    length=max_length;
661
664
  *to++= (char) (length & 255);
667
670
}
668
671
 
669
672
 
670
 
uint32_t Field_blob::packed_col_length(const unsigned char *data_ptr, uint32_t length)
 
673
uint Field_blob::packed_col_length(const uchar *data_ptr, uint length)
671
674
{
672
675
  if (length > 255)
673
676
    return uint2korr(data_ptr)+2;
675
678
}
676
679
 
677
680
 
678
 
uint32_t Field_blob::max_packed_col_length(uint32_t max_length)
 
681
uint Field_blob::max_packed_col_length(uint max_length)
679
682
{
680
683
  return (max_length > 255 ? 2 : 1)+max_length;
681
684
}
682
685
 
683
686
 
684
 
uint32_t Field_blob::is_equal(Create_field *new_field)
 
687
uint Field_blob::is_equal(Create_field *new_field)
685
688
{
686
689
  if (compare_str_field_flags(new_field, flags))
687
690
    return 0;