~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/field/blob.cc

  • Committer: Toru Maesaka
  • Date: 2008-07-17 05:59:20 UTC
  • mto: (202.1.1 toru)
  • mto: This revision was merged to the branch mainline in revision 204.
  • Revision ID: dev@torum.net-20080717055920-10okif50x6nh7b1d
forgot to bzr-add new files in the previous push

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
22
22
#pragma implementation                          // gcc: Class implementation
23
23
#endif
24
24
 
25
 
#include <drizzled/server_includes.h>
26
 
#include <drizzled/field/blob.h>
27
 
 
28
 
uint32_t
29
 
blob_pack_length_to_max_length(uint32_t arg)
30
 
{
31
 
  return (INT64_C(1) << cmin(arg, 4U) * 8) - INT64_C(1);
32
 
}
33
 
 
 
25
#include "blob.h"
 
26
 
 
27
#define BLOB_PACK_LENGTH_TO_MAX_LENGH(arg) \
 
28
((ulong) ((1LL << min(arg, 4) * 8) - 1LL))
34
29
 
35
30
/****************************************************************************
36
31
** blob type
38
33
** packlength slot and may be from 1-4.
39
34
****************************************************************************/
40
35
 
41
 
Field_blob::Field_blob(unsigned char *ptr_arg, unsigned char *null_ptr_arg, unsigned char null_bit_arg,
 
36
Field_blob::Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
42
37
                       enum utype unireg_check_arg, const char *field_name_arg,
43
 
                       TABLE_SHARE *share, uint32_t blob_pack_length,
44
 
                       const CHARSET_INFO * const cs)
45
 
  :Field_longstr(ptr_arg, blob_pack_length_to_max_length(blob_pack_length),
 
38
                       TABLE_SHARE *share, uint blob_pack_length,
 
39
                       CHARSET_INFO *cs)
 
40
  :Field_longstr(ptr_arg, BLOB_PACK_LENGTH_TO_MAX_LENGH(blob_pack_length),
46
41
                 null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
47
42
                 cs),
48
43
   packlength(blob_pack_length)
53
48
}
54
49
 
55
50
 
56
 
void Field_blob::store_length(unsigned char *i_ptr,
57
 
                              uint32_t i_packlength,
 
51
void Field_blob::store_length(uchar *i_ptr,
 
52
                              uint i_packlength,
58
53
                              uint32_t i_number,
59
 
                              bool low_byte_first __attribute__((unused)))
 
54
                              bool low_byte_first __attribute__((__unused__)))
60
55
{
61
56
  switch (i_packlength) {
62
57
  case 1:
63
 
    i_ptr[0]= (unsigned char) i_number;
 
58
    i_ptr[0]= (uchar) i_number;
64
59
    break;
65
60
  case 2:
66
61
#ifdef WORDS_BIGENDIAN
88
83
}
89
84
 
90
85
 
91
 
uint32_t Field_blob::get_length(const unsigned char *pos,
92
 
                              uint32_t packlength_arg,
93
 
                              bool low_byte_first __attribute__((unused)))
 
86
uint32_t Field_blob::get_length(const uchar *pos,
 
87
                              uint packlength_arg,
 
88
                              bool low_byte_first __attribute__((__unused__)))
94
89
{
95
90
  switch (packlength_arg) {
96
91
  case 1:
97
92
    return (uint32_t) pos[0];
98
93
  case 2:
99
94
    {
100
 
      uint16_t tmp;
 
95
      uint16 tmp;
101
96
#ifdef WORDS_BIGENDIAN
102
97
      if (low_byte_first)
103
98
        tmp=sint2korr(pos);
135
130
  @param length              The length value to put.
136
131
*/
137
132
 
138
 
void Field_blob::put_length(unsigned char *pos, uint32_t length)
 
133
void Field_blob::put_length(uchar *pos, uint32_t length)
139
134
{
140
135
  switch (packlength) {
141
136
  case 1:
154
149
}
155
150
 
156
151
 
157
 
int Field_blob::store(const char *from,uint32_t length, const CHARSET_INFO * const cs)
 
152
int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
158
153
{
159
 
  uint32_t copy_length, new_length;
 
154
  uint copy_length, new_length;
160
155
  const char *well_formed_error_pos;
161
156
  const char *cannot_convert_error_pos;
162
157
  const char *from_end_pos, *tmp;
165
160
 
166
161
  if (!length)
167
162
  {
168
 
    memset(ptr, 0, Field_blob::pack_length());
 
163
    bzero(ptr,Field_blob::pack_length());
169
164
    return 0;
170
165
  }
171
166
 
175
170
    if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
176
171
    {
177
172
      Field_blob::store_length(length);
178
 
      memcpy(ptr+packlength, &from, sizeof(char*));
 
173
      bmove(ptr+packlength,(char*) &from,sizeof(char*));
179
174
      return 0;
180
175
    }
181
176
    if (tmpstr.copy(from, length, cs))
183
178
    from= tmpstr.ptr();
184
179
  }
185
180
 
186
 
  new_length= cmin(max_data_length(), field_charset->mbmaxlen * length);
 
181
  new_length= min(max_data_length(), field_charset->mbmaxlen * length);
187
182
  if (value.alloc(new_length))
188
183
    goto oom_error;
189
184
 
195
190
                                            from, length);
196
191
    Field_blob::store_length(copy_length);
197
192
    tmp= value.ptr();
198
 
    memcpy(ptr + packlength, &tmp, sizeof(char*));
 
193
    bmove(ptr + packlength, (uchar*) &tmp, sizeof(char*));
199
194
    return 0;
200
195
  }
201
196
  /*
213
208
 
214
209
  Field_blob::store_length(copy_length);
215
210
  tmp= value.ptr();
216
 
  memcpy(ptr+packlength, &tmp, sizeof(char*));
 
211
  bmove(ptr+packlength,(uchar*) &tmp,sizeof(char*));
217
212
 
218
213
  if (check_string_copy_error(this, well_formed_error_pos,
219
214
                              cannot_convert_error_pos, from + length, cs))
223
218
 
224
219
oom_error:
225
220
  /* Fatal OOM error */
226
 
  memset(ptr, 0, Field_blob::pack_length());
 
221
  bzero(ptr,Field_blob::pack_length());
227
222
  return -1; 
228
223
}
229
224
 
230
225
 
231
226
int Field_blob::store(double nr)
232
227
{
233
 
  const CHARSET_INFO * const cs=charset();
 
228
  CHARSET_INFO *cs=charset();
234
229
  value.set_real(nr, NOT_FIXED_DEC, cs);
235
230
  return Field_blob::store(value.ptr(),(uint) value.length(), cs);
236
231
}
238
233
 
239
234
int Field_blob::store(int64_t nr, bool unsigned_val)
240
235
{
241
 
  const CHARSET_INFO * const cs=charset();
 
236
  CHARSET_INFO *cs=charset();
242
237
  value.set_int(nr, unsigned_val, cs);
243
238
  return Field_blob::store(value.ptr(), (uint) value.length(), cs);
244
239
}
249
244
  int not_used;
250
245
  char *end_not_used, *blob;
251
246
  uint32_t length;
252
 
  const CHARSET_INFO *cs;
 
247
  CHARSET_INFO *cs;
253
248
 
254
 
  memcpy(&blob,ptr+packlength,sizeof(char*));
 
249
  memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
255
250
  if (!blob)
256
251
    return 0.0;
257
252
  length= get_length(ptr);
264
259
{
265
260
  int not_used;
266
261
  char *blob;
267
 
  memcpy(&blob,ptr+packlength,sizeof(char*));
 
262
  memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
268
263
  if (!blob)
269
264
    return 0;
270
265
  uint32_t length=get_length(ptr);
275
270
                            String *val_ptr)
276
271
{
277
272
  char *blob;
278
 
  memcpy(&blob,ptr+packlength,sizeof(char*));
 
273
  memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
279
274
  if (!blob)
280
275
    val_ptr->set("",0,charset());       // A bit safer than ->length(0)
281
276
  else
288
283
{
289
284
  const char *blob;
290
285
  size_t length;
291
 
  memcpy(&blob, ptr+packlength, sizeof(const unsigned char*));
 
286
  memcpy_fixed(&blob, ptr+packlength, sizeof(const uchar*));
292
287
  if (!blob)
293
288
  {
294
289
    blob= "";
303
298
}
304
299
 
305
300
 
306
 
int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
 
301
int Field_blob::cmp(const uchar *a,uint32_t a_length, const uchar *b,
307
302
                    uint32_t b_length)
308
303
{
309
304
  return field_charset->coll->strnncollsp(field_charset, 
312
307
}
313
308
 
314
309
 
315
 
int Field_blob::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
316
 
                        uint32_t max_length)
 
310
int Field_blob::cmp_max(const uchar *a_ptr, const uchar *b_ptr,
 
311
                        uint max_length)
317
312
{
318
 
  unsigned char *blob1,*blob2;
319
 
  memcpy(&blob1,a_ptr+packlength,sizeof(char*));
320
 
  memcpy(&blob2,b_ptr+packlength,sizeof(char*));
321
 
  uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
 
313
  uchar *blob1,*blob2;
 
314
  memcpy_fixed(&blob1,a_ptr+packlength,sizeof(char*));
 
315
  memcpy_fixed(&blob2,b_ptr+packlength,sizeof(char*));
 
316
  uint a_len= get_length(a_ptr), b_len= get_length(b_ptr);
322
317
  set_if_smaller(a_len, max_length);
323
318
  set_if_smaller(b_len, max_length);
324
319
  return Field_blob::cmp(blob1,a_len,blob2,b_len);
325
320
}
326
321
 
327
322
 
328
 
int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
 
323
int Field_blob::cmp_binary(const uchar *a_ptr, const uchar *b_ptr,
329
324
                           uint32_t max_length)
330
325
{
331
326
  char *a,*b;
332
 
  uint32_t diff;
 
327
  uint diff;
333
328
  uint32_t a_length,b_length;
334
 
  memcpy(&a,a_ptr+packlength,sizeof(char*));
335
 
  memcpy(&b,b_ptr+packlength,sizeof(char*));
 
329
  memcpy_fixed(&a,a_ptr+packlength,sizeof(char*));
 
330
  memcpy_fixed(&b,b_ptr+packlength,sizeof(char*));
336
331
  a_length=get_length(a_ptr);
337
332
  if (a_length > max_length)
338
333
    a_length=max_length;
339
334
  b_length=get_length(b_ptr);
340
335
  if (b_length > max_length)
341
336
    b_length=max_length;
342
 
  diff=memcmp(a,b,cmin(a_length,b_length));
 
337
  diff=memcmp(a,b,min(a_length,b_length));
343
338
  return diff ? diff : (int) (a_length - b_length);
344
339
}
345
340
 
346
341
 
347
342
/* The following is used only when comparing a key */
348
343
 
349
 
uint32_t Field_blob::get_key_image(unsigned char *buff,
350
 
                               uint32_t length,
351
 
                               imagetype type_arg __attribute__((unused)))
 
344
uint Field_blob::get_key_image(uchar *buff,
 
345
                               uint length,
 
346
                               imagetype type_arg __attribute__((__unused__)))
352
347
{
353
348
  uint32_t blob_length= get_length(ptr);
354
 
  unsigned char *blob;
 
349
  uchar *blob;
355
350
 
356
351
  get_ptr(&blob);
357
 
  uint32_t local_char_length= length / field_charset->mbmaxlen;
 
352
  uint local_char_length= length / field_charset->mbmaxlen;
358
353
  local_char_length= my_charpos(field_charset, blob, blob + blob_length,
359
354
                          local_char_length);
360
355
  set_if_smaller(blob_length, local_char_length);
365
360
      Must clear this as we do a memcmp in opt_range.cc to detect
366
361
      identical keys
367
362
    */
368
 
    memset(buff+HA_KEY_BLOB_LENGTH+blob_length, 0, (length-blob_length));
 
363
    bzero(buff+HA_KEY_BLOB_LENGTH+blob_length, (length-blob_length));
369
364
    length=(uint) blob_length;
370
365
  }
371
366
  int2store(buff,length);
374
369
}
375
370
 
376
371
 
377
 
void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
 
372
void Field_blob::set_key_image(const uchar *buff,uint length)
378
373
{
379
374
  length= uint2korr(buff);
380
375
  (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length,
382
377
}
383
378
 
384
379
 
385
 
int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
 
380
int Field_blob::key_cmp(const uchar *key_ptr, uint max_key_length)
386
381
{
387
 
  unsigned char *blob1;
388
 
  uint32_t blob_length=get_length(ptr);
389
 
  memcpy(&blob1,ptr+packlength,sizeof(char*));
390
 
  const CHARSET_INFO * const cs= charset();
391
 
  uint32_t local_char_length= max_key_length / cs->mbmaxlen;
 
382
  uchar *blob1;
 
383
  uint blob_length=get_length(ptr);
 
384
  memcpy_fixed(&blob1,ptr+packlength,sizeof(char*));
 
385
  CHARSET_INFO *cs= charset();
 
386
  uint local_char_length= max_key_length / cs->mbmaxlen;
392
387
  local_char_length= my_charpos(cs, blob1, blob1+blob_length,
393
388
                                local_char_length);
394
389
  set_if_smaller(blob_length, local_char_length);
397
392
                         uint2korr(key_ptr));
398
393
}
399
394
 
400
 
int Field_blob::key_cmp(const unsigned char *a,const unsigned char *b)
 
395
int Field_blob::key_cmp(const uchar *a,const uchar *b)
401
396
{
402
397
  return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
403
398
                         b+HA_KEY_BLOB_LENGTH, uint2korr(b));
414
409
 
415
410
   @returns number of bytes written to metadata_ptr
416
411
*/
417
 
int Field_blob::do_save_field_metadata(unsigned char *metadata_ptr)
 
412
int Field_blob::do_save_field_metadata(uchar *metadata_ptr)
418
413
{
419
414
  *metadata_ptr= pack_length_no_ptr();
420
415
  return 1;
428
423
}
429
424
 
430
425
 
431
 
void Field_blob::sort_string(unsigned char *to,uint32_t length)
 
426
void Field_blob::sort_string(uchar *to,uint length)
432
427
{
433
 
  unsigned char *blob;
434
 
  uint32_t blob_length=get_length();
 
428
  uchar *blob;
 
429
  uint blob_length=get_length();
435
430
 
436
431
  if (!blob_length)
437
 
    memset(to, 0, length);
 
432
    bzero(to,length);
438
433
  else
439
434
  {
440
435
    if (field_charset == &my_charset_bin)
441
436
    {
442
 
      unsigned char *pos;
 
437
      uchar *pos;
443
438
 
444
439
      /*
445
440
        Store length of blob last in blob to shorter blobs before longer blobs
462
457
        break;
463
458
      }
464
459
    }
465
 
    memcpy(&blob,ptr+packlength,sizeof(char*));
 
460
    memcpy_fixed(&blob,ptr+packlength,sizeof(char*));
466
461
    
467
462
    blob_length=my_strnxfrm(field_charset,
468
463
                            to, length, blob, blob_length);
473
468
 
474
469
void Field_blob::sql_type(String &res) const
475
470
{
 
471
  const char *str;
 
472
  uint length;
 
473
  switch (packlength) {
 
474
  default: str="tiny"; length=4; break;
 
475
  case 2:  str="";     length=0; break;
 
476
  case 3:  str="medium"; length= 6; break;
 
477
  case 4:  str="long";  length=4; break;
 
478
  }
 
479
  res.set_ascii(str,length);
476
480
  if (charset() == &my_charset_bin)
477
 
    res.set_ascii(STRING_WITH_LEN("blob"));
 
481
    res.append(STRING_WITH_LEN("blob"));
478
482
  else
479
 
    res.set_ascii(STRING_WITH_LEN("text"));
 
483
  {
 
484
    res.append(STRING_WITH_LEN("text"));
 
485
  }
480
486
}
481
487
 
482
 
unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
483
 
                        uint32_t max_length, bool low_byte_first)
 
488
uchar *Field_blob::pack(uchar *to, const uchar *from,
 
489
                        uint max_length, bool low_byte_first)
484
490
{
485
 
  unsigned char *save= ptr;
486
 
  ptr= (unsigned char*) from;
 
491
  uchar *save= ptr;
 
492
  ptr= (uchar*) from;
487
493
  uint32_t length=get_length();                 // Length of from string
488
494
 
489
495
  /*
491
497
    length given is smaller than the actual length of the blob, we
492
498
    just store the initial bytes of the blob.
493
499
  */
494
 
  store_length(to, packlength, cmin(length, max_length), low_byte_first);
 
500
  store_length(to, packlength, min(length, max_length), low_byte_first);
495
501
 
496
502
  /*
497
503
    Store the actual blob data, which will occupy 'length' bytes.
498
504
   */
499
505
  if (length > 0)
500
506
  {
501
 
    get_ptr((unsigned char**) &from);
 
507
    get_ptr((uchar**) &from);
502
508
    memcpy(to+packlength, from,length);
503
509
  }
504
510
  ptr=save;                                     // Restore org row pointer
523
529
 
524
530
   @return  New pointer into memory based on from + length of the data
525
531
*/
526
 
const unsigned char *Field_blob::unpack(unsigned char *to __attribute__((unused)),
527
 
                                const unsigned char *from,
528
 
                                uint32_t param_data,
 
532
const uchar *Field_blob::unpack(uchar *to __attribute__((__unused__)),
 
533
                                const uchar *from,
 
534
                                uint param_data,
529
535
                                bool low_byte_first)
530
536
{
531
 
  uint32_t const master_packlength=
 
537
  uint const master_packlength=
532
538
    param_data > 0 ? param_data & 0xFF : packlength;
533
539
  uint32_t const length= get_length(from, master_packlength, low_byte_first);
534
540
  bitmap_set_bit(table->write_set, field_index);
539
545
 
540
546
/* Keys for blobs are like keys on varchars */
541
547
 
542
 
int Field_blob::pack_cmp(const unsigned char *a, const unsigned char *b, uint32_t key_length_arg,
543
 
                         bool insert_or_update)
 
548
int Field_blob::pack_cmp(const uchar *a, const uchar *b, uint key_length_arg,
 
549
                         my_bool insert_or_update)
544
550
{
545
 
  uint32_t a_length, b_length;
 
551
  uint a_length, b_length;
546
552
  if (key_length_arg > 255)
547
553
  {
548
554
    a_length=uint2korr(a); a+=2;
560
566
}
561
567
 
562
568
 
563
 
int Field_blob::pack_cmp(const unsigned char *b, uint32_t key_length_arg,
564
 
                         bool insert_or_update)
 
569
int Field_blob::pack_cmp(const uchar *b, uint key_length_arg,
 
570
                         my_bool insert_or_update)
565
571
{
566
 
  unsigned char *a;
567
 
  uint32_t a_length, b_length;
568
 
  memcpy(&a,ptr+packlength,sizeof(char*));
 
572
  uchar *a;
 
573
  uint a_length, b_length;
 
574
  memcpy_fixed(&a,ptr+packlength,sizeof(char*));
569
575
  if (!a)
570
576
    return key_length_arg > 0 ? -1 : 0;
571
577
 
584
590
 
585
591
/** Create a packed key that will be used for storage from a MySQL row. */
586
592
 
587
 
unsigned char *
588
 
Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
 
593
uchar *
 
594
Field_blob::pack_key(uchar *to, const uchar *from, uint max_length,
589
595
                     bool low_byte_first __attribute__((unused)))
590
596
{
591
 
  unsigned char *save= ptr;
592
 
  ptr= (unsigned char*) from;
 
597
  uchar *save= ptr;
 
598
  ptr= (uchar*) from;
593
599
  uint32_t length=get_length();        // Length of from string
594
 
  uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
 
600
  uint local_char_length= ((field_charset->mbmaxlen > 1) ?
595
601
                           max_length/field_charset->mbmaxlen : max_length);
596
602
  if (length)
597
 
    get_ptr((unsigned char**) &from);
 
603
    get_ptr((uchar**) &from);
598
604
  if (length > local_char_length)
599
605
    local_char_length= my_charpos(field_charset, from, from+length,
600
606
                                  local_char_length);
601
607
  set_if_smaller(length, local_char_length);
602
 
  *to++= (unsigned char) length;
 
608
  *to++= (uchar) length;
603
609
  if (max_length > 255)                         // 2 byte length
604
 
    *to++= (unsigned char) (length >> 8);
 
610
    *to++= (uchar) (length >> 8);
605
611
  memcpy(to, from, length);
606
612
  ptr=save;                                     // Restore org row pointer
607
613
  return to+length;
629
635
    Pointer into 'from' past the last byte copied from packed key.
630
636
*/
631
637
 
632
 
const unsigned char *
633
 
Field_blob::unpack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
 
638
const uchar *
 
639
Field_blob::unpack_key(uchar *to, const uchar *from, uint max_length,
634
640
                       bool low_byte_first __attribute__((unused)))
635
641
{
636
642
  /* get length of the blob key */
643
649
 
644
650
  /* put the address of the blob buffer or NULL */
645
651
  if (length)
646
 
    memcpy(to + packlength, &from, sizeof(from));
 
652
    memcpy_fixed(to + packlength, &from, sizeof(from));
647
653
  else
648
 
    memset(to + packlength, 0, sizeof(from));
 
654
    bzero(to + packlength, sizeof(from));
649
655
 
650
656
  /* point to first byte of next field in 'from' */
651
657
  return from + length;
654
660
 
655
661
/** Create a packed key that will be used for storage from a MySQL key. */
656
662
 
657
 
unsigned char *
658
 
Field_blob::pack_key_from_key_image(unsigned char *to, const unsigned char *from, uint32_t max_length,
 
663
uchar *
 
664
Field_blob::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length,
659
665
                                    bool low_byte_first __attribute__((unused)))
660
666
{
661
 
  uint32_t length=uint2korr(from);
 
667
  uint length=uint2korr(from);
662
668
  if (length > max_length)
663
669
    length=max_length;
664
670
  *to++= (char) (length & 255);
670
676
}
671
677
 
672
678
 
673
 
uint32_t Field_blob::packed_col_length(const unsigned char *data_ptr, uint32_t length)
 
679
uint Field_blob::packed_col_length(const uchar *data_ptr, uint length)
674
680
{
675
681
  if (length > 255)
676
682
    return uint2korr(data_ptr)+2;
678
684
}
679
685
 
680
686
 
681
 
uint32_t Field_blob::max_packed_col_length(uint32_t max_length)
 
687
uint Field_blob::max_packed_col_length(uint max_length)
682
688
{
683
689
  return (max_length > 255 ? 2 : 1)+max_length;
684
690
}
685
691
 
686
692
 
687
 
uint32_t Field_blob::is_equal(Create_field *new_field)
 
693
uint Field_blob::is_equal(Create_field *new_field)
688
694
{
689
695
  if (compare_str_field_flags(new_field, flags))
690
696
    return 0;