~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

Merged in changes from Andrey.

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