~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

  • Committer: Monty
  • Date: 2008-11-07 05:51:15 UTC
  • mto: This revision was merged to the branch mainline in revision 579.
  • Revision ID: mordred@palanthas.inaugust.com-20081107055115-0275gvq62buzls77
Fixed a decimal sign thing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 */
20
20
 
21
21
 
22
 
#include "config.h"
 
22
#include <drizzled/server_includes.h>
23
23
#include <drizzled/field/blob.h>
24
 
#include <drizzled/table.h>
25
 
#include <drizzled/session.h>
26
 
#include "plugin/myisam/myisam.h"
27
 
 
28
 
#include <string>
29
 
#include <algorithm>
30
 
 
31
 
using namespace std;
32
 
 
33
 
namespace drizzled
34
 
{
35
 
 
36
 
static uint32_t blob_pack_length_to_max_length(uint32_t arg)
37
 
{
38
 
  return max(UINT32_MAX,
39
 
             (uint32_t)((INT64_C(1) << min(arg, 4U) * 8) - INT64_C(1)));
 
24
 
 
25
uint32_t
 
26
blob_pack_length_to_max_length(uint32_t arg)
 
27
{
 
28
  return (INT64_C(1) << cmin(arg, 4U) * 8) - INT64_C(1);
40
29
}
41
30
 
42
31
 
43
32
/****************************************************************************
44
33
** blob type
45
34
** 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)
 
35
** packlength slot and may be from 1-4.
47
36
****************************************************************************/
48
37
 
49
 
Field_blob::Field_blob(unsigned char *ptr_arg,
50
 
                       unsigned char *null_ptr_arg,
51
 
                       unsigned char null_bit_arg,
52
 
                                   const char *field_name_arg,
53
 
                       TableShare *share,
54
 
                       const CHARSET_INFO * const cs)
55
 
  :Field_str(ptr_arg,
56
 
             blob_pack_length_to_max_length(sizeof(uint32_t)),
57
 
             null_ptr_arg,
58
 
             null_bit_arg,
59
 
             field_name_arg,
60
 
             cs)
 
38
Field_blob::Field_blob(unsigned char *ptr_arg, unsigned char *null_ptr_arg, unsigned char null_bit_arg,
 
39
                       enum utype unireg_check_arg, const char *field_name_arg,
 
40
                       TABLE_SHARE *share, uint32_t blob_pack_length,
 
41
                       const CHARSET_INFO * const cs)
 
42
  :Field_longstr(ptr_arg, blob_pack_length_to_max_length(blob_pack_length),
 
43
                 null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
 
44
                 cs),
 
45
   packlength(blob_pack_length)
61
46
{
62
47
  flags|= BLOB_FLAG;
63
48
  share->blob_fields++;
64
 
  /* TODO: why do not fill table->getShare()->blob_field array here? */
 
49
  /* TODO: why do not fill table->s->blob_field array here? */
65
50
}
66
51
 
 
52
 
67
53
void Field_blob::store_length(unsigned char *i_ptr,
 
54
                              uint32_t i_packlength,
68
55
                              uint32_t i_number,
69
 
                              bool low_byte_first)
 
56
                              bool low_byte_first __attribute__((unused)))
70
57
{
71
 
#ifndef WORDS_BIGENDIAN
72
 
  (void)low_byte_first;
73
 
#endif
74
 
 
75
 
#ifdef WORDS_BIGENDIAN
76
 
  if (low_byte_first)
77
 
  {
78
 
    int4store(i_ptr,i_number);
 
58
  switch (i_packlength) {
 
59
  case 1:
 
60
    i_ptr[0]= (unsigned char) i_number;
 
61
    break;
 
62
  case 2:
 
63
#ifdef WORDS_BIGENDIAN
 
64
    if (low_byte_first)
 
65
    {
 
66
      int2store(i_ptr,(unsigned short) i_number);
 
67
    }
 
68
    else
 
69
#endif
 
70
      shortstore(i_ptr,(unsigned short) i_number);
 
71
    break;
 
72
  case 3:
 
73
    int3store(i_ptr,i_number);
 
74
    break;
 
75
  case 4:
 
76
#ifdef WORDS_BIGENDIAN
 
77
    if (low_byte_first)
 
78
    {
 
79
      int4store(i_ptr,i_number);
 
80
    }
 
81
    else
 
82
#endif
 
83
      longstore(i_ptr,i_number);
79
84
  }
80
 
  else
81
 
#endif
82
 
    longstore(i_ptr,i_number);
83
 
}
84
 
 
85
 
 
86
 
void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_number)
87
 
{
88
 
  store_length(i_ptr, i_number, getTable()->getShare()->db_low_byte_first);
89
85
}
90
86
 
91
87
 
92
88
uint32_t Field_blob::get_length(const unsigned char *pos,
93
 
                                bool low_byte_first)
94
 
{
95
 
#ifndef WORDS_BIGENDIAN
96
 
  (void)low_byte_first;
97
 
#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;
106
 
}
107
 
 
108
 
 
109
 
uint32_t Field_blob::get_packed_size(const unsigned char *ptr_arg,
110
 
                                bool low_byte_first)
111
 
{
112
 
  return sizeof(uint32_t) + get_length(ptr_arg, low_byte_first);
113
 
}
114
 
 
115
 
 
116
 
uint32_t Field_blob::get_length(uint32_t row_offset)
117
 
{
118
 
  return get_length(ptr+row_offset,
119
 
                    getTable()->getShare()->db_low_byte_first);
120
 
}
121
 
 
122
 
 
123
 
uint32_t Field_blob::get_length(const unsigned char *ptr_arg)
124
 
{
125
 
  return get_length(ptr_arg, getTable()->getShare()->db_low_byte_first);
 
89
                              uint32_t packlength_arg,
 
90
                              bool low_byte_first __attribute__((unused)))
 
91
{
 
92
  switch (packlength_arg) {
 
93
  case 1:
 
94
    return (uint32_t) pos[0];
 
95
  case 2:
 
96
    {
 
97
      uint16_t tmp;
 
98
#ifdef WORDS_BIGENDIAN
 
99
      if (low_byte_first)
 
100
        tmp=sint2korr(pos);
 
101
      else
 
102
#endif
 
103
        shortget(tmp,pos);
 
104
      return (uint32_t) tmp;
 
105
    }
 
106
  case 3:
 
107
    return (uint32_t) uint3korr(pos);
 
108
  case 4:
 
109
    {
 
110
      uint32_t tmp;
 
111
#ifdef WORDS_BIGENDIAN
 
112
      if (low_byte_first)
 
113
        tmp=uint4korr(pos);
 
114
      else
 
115
#endif
 
116
        longget(tmp,pos);
 
117
      return (uint32_t) tmp;
 
118
    }
 
119
  }
 
120
  return 0;                                     // Impossible
126
121
}
127
122
 
128
123
 
129
124
/**
130
125
  Put a blob length field into a record buffer.
131
126
 
132
 
  Blob length is always stored in sizeof(uint32_t) (4 bytes)
 
127
  Depending on the maximum length of a blob, its length field is
 
128
  put into 1 to 4 bytes. This is a property of the blob object,
 
129
  described by 'packlength'.
133
130
 
134
131
  @param pos                 Pointer into the record buffer.
135
132
  @param length              The length value to put.
137
134
 
138
135
void Field_blob::put_length(unsigned char *pos, uint32_t length)
139
136
{
 
137
  switch (packlength) {
 
138
  case 1:
 
139
    *pos= (char) length;
 
140
    break;
 
141
  case 2:
 
142
    int2store(pos, length);
 
143
    break;
 
144
  case 3:
 
145
    int3store(pos, length);
 
146
    break;
 
147
  case 4:
140
148
    int4store(pos, length);
 
149
    break;
 
150
  }
141
151
}
142
152
 
143
153
 
150
160
  char buff[STRING_BUFFER_USUAL_SIZE];
151
161
  String tmpstr(buff,sizeof(buff), &my_charset_bin);
152
162
 
153
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
154
 
 
155
163
  if (!length)
156
164
  {
157
165
    memset(ptr, 0, Field_blob::pack_length());
160
168
 
161
169
  if (from == value.ptr())
162
170
  {
163
 
    size_t dummy_offset;
 
171
    uint32_t dummy_offset;
164
172
    if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
165
173
    {
166
174
      Field_blob::store_length(length);
167
 
      memmove(ptr+sizeof(uint32_t), &from, sizeof(char*));
 
175
      memcpy(ptr+packlength, &from, sizeof(char*));
168
176
      return 0;
169
177
    }
170
178
    if (tmpstr.copy(from, length, cs))
172
180
    from= tmpstr.ptr();
173
181
  }
174
182
 
175
 
  new_length= min(max_data_length(), field_charset->mbmaxlen * length);
 
183
  new_length= cmin(max_data_length(), field_charset->mbmaxlen * length);
176
184
  if (value.alloc(new_length))
177
185
    goto oom_error;
178
186
 
 
187
 
 
188
  if (f_is_hex_escape(flags))
 
189
  {
 
190
    copy_length= my_copy_with_hex_escaping(field_charset,
 
191
                                           (char*) value.ptr(), new_length,
 
192
                                            from, length);
 
193
    Field_blob::store_length(copy_length);
 
194
    tmp= value.ptr();
 
195
    memcpy(ptr + packlength, &tmp, sizeof(char*));
 
196
    return 0;
 
197
  }
179
198
  /*
180
199
    "length" is OK as "nchars" argument to well_formed_copy_nchars as this
181
200
    is never used to limit the length of the data. The cut of long data
191
210
 
192
211
  Field_blob::store_length(copy_length);
193
212
  tmp= value.ptr();
194
 
  memmove(ptr+sizeof(uint32_t), &tmp, sizeof(char*));
 
213
  memcpy(ptr+packlength, &tmp, sizeof(char*));
195
214
 
196
215
  if (check_string_copy_error(this, well_formed_error_pos,
197
216
                              cannot_convert_error_pos, from + length, cs))
202
221
oom_error:
203
222
  /* Fatal OOM error */
204
223
  memset(ptr, 0, Field_blob::pack_length());
205
 
  return -1;
 
224
  return -1; 
206
225
}
207
226
 
208
227
 
209
228
int Field_blob::store(double nr)
210
229
{
211
230
  const CHARSET_INFO * const cs=charset();
212
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
213
231
  value.set_real(nr, NOT_FIXED_DEC, cs);
214
 
  return Field_blob::store(value.ptr(),(uint32_t) value.length(), cs);
 
232
  return Field_blob::store(value.ptr(),(uint) value.length(), cs);
215
233
}
216
234
 
217
235
 
218
236
int Field_blob::store(int64_t nr, bool unsigned_val)
219
237
{
220
238
  const CHARSET_INFO * const cs=charset();
221
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
222
239
  value.set_int(nr, unsigned_val, cs);
223
 
  return Field_blob::store(value.ptr(), (uint32_t) value.length(), cs);
 
240
  return Field_blob::store(value.ptr(), (uint) value.length(), cs);
224
241
}
225
242
 
226
243
 
231
248
  uint32_t length;
232
249
  const CHARSET_INFO *cs;
233
250
 
234
 
  ASSERT_COLUMN_MARKED_FOR_READ;
235
 
 
236
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
251
  memcpy(&blob,ptr+packlength,sizeof(char*));
237
252
  if (!blob)
238
253
    return 0.0;
239
254
  length= get_length(ptr);
246
261
{
247
262
  int not_used;
248
263
  char *blob;
249
 
 
250
 
  ASSERT_COLUMN_MARKED_FOR_READ;
251
 
 
252
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
264
  memcpy(&blob,ptr+packlength,sizeof(char*));
253
265
  if (!blob)
254
266
    return 0;
255
267
  uint32_t length=get_length(ptr);
256
268
  return my_strntoll(charset(),blob,length,10,NULL,&not_used);
257
269
}
258
270
 
259
 
String *Field_blob::val_str(String *,
 
271
String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
260
272
                            String *val_ptr)
261
273
{
262
274
  char *blob;
263
 
 
264
 
  ASSERT_COLUMN_MARKED_FOR_READ;
265
 
 
266
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
275
  memcpy(&blob,ptr+packlength,sizeof(char*));
267
276
  if (!blob)
268
277
    val_ptr->set("",0,charset());       // A bit safer than ->length(0)
269
278
  else
272
281
}
273
282
 
274
283
 
275
 
type::Decimal *Field_blob::val_decimal(type::Decimal *decimal_value)
 
284
my_decimal *Field_blob::val_decimal(my_decimal *decimal_value)
276
285
{
277
286
  const char *blob;
278
287
  size_t length;
279
 
 
280
 
  ASSERT_COLUMN_MARKED_FOR_READ;
281
 
 
282
 
  memcpy(&blob, ptr+sizeof(uint32_t), sizeof(const unsigned char*));
 
288
  memcpy(&blob, ptr+packlength, sizeof(const unsigned char*));
283
289
  if (!blob)
284
290
  {
285
291
    blob= "";
286
292
    length= 0;
287
293
  }
288
294
  else
289
 
  {
290
295
    length= get_length(ptr);
291
 
  }
292
 
 
293
 
  decimal_value->store(E_DEC_FATAL_ERROR, blob, length, charset());
294
 
 
 
296
 
 
297
  str2my_decimal(E_DEC_FATAL_ERROR, blob, length, charset(),
 
298
                 decimal_value);
295
299
  return decimal_value;
296
300
}
297
301
 
299
303
int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
300
304
                    uint32_t b_length)
301
305
{
302
 
  return field_charset->coll->strnncollsp(field_charset,
 
306
  return field_charset->coll->strnncollsp(field_charset, 
303
307
                                          a, a_length, b, b_length,
304
308
                                          0);
305
309
}
309
313
                        uint32_t max_length)
310
314
{
311
315
  unsigned char *blob1,*blob2;
312
 
  memcpy(&blob1,a_ptr+sizeof(uint32_t),sizeof(char*));
313
 
  memcpy(&blob2,b_ptr+sizeof(uint32_t),sizeof(char*));
 
316
  memcpy(&blob1,a_ptr+packlength,sizeof(char*));
 
317
  memcpy(&blob2,b_ptr+packlength,sizeof(char*));
314
318
  uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
315
319
  set_if_smaller(a_len, max_length);
316
320
  set_if_smaller(b_len, max_length);
319
323
 
320
324
 
321
325
int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
322
 
                           uint32_t max_length)
 
326
                           uint32_t max_length)
323
327
{
324
328
  char *a,*b;
325
329
  uint32_t diff;
326
330
  uint32_t a_length,b_length;
327
 
  memcpy(&a,a_ptr+sizeof(uint32_t),sizeof(char*));
328
 
  memcpy(&b,b_ptr+sizeof(uint32_t),sizeof(char*));
329
 
 
330
 
  a_length= get_length(a_ptr);
331
 
 
 
331
  memcpy(&a,a_ptr+packlength,sizeof(char*));
 
332
  memcpy(&b,b_ptr+packlength,sizeof(char*));
 
333
  a_length=get_length(a_ptr);
332
334
  if (a_length > max_length)
333
 
    a_length= max_length;
334
 
 
335
 
  b_length= get_length(b_ptr);
336
 
 
 
335
    a_length=max_length;
 
336
  b_length=get_length(b_ptr);
337
337
  if (b_length > max_length)
338
 
    b_length= max_length;
339
 
 
340
 
  diff= memcmp(a,b,min(a_length,b_length));
341
 
 
342
 
  return diff ? diff : (unsigned int) (a_length - b_length);
 
338
    b_length=max_length;
 
339
  diff=memcmp(a,b,cmin(a_length,b_length));
 
340
  return diff ? diff : (int) (a_length - b_length);
343
341
}
344
342
 
 
343
 
345
344
/* The following is used only when comparing a key */
346
 
uint32_t Field_blob::get_key_image(unsigned char *buff, uint32_t length)
 
345
 
 
346
uint32_t Field_blob::get_key_image(unsigned char *buff,
 
347
                               uint32_t length,
 
348
                               imagetype type_arg __attribute__((unused)))
347
349
{
348
350
  uint32_t blob_length= get_length(ptr);
349
351
  unsigned char *blob;
357
359
  if ((uint32_t) length > blob_length)
358
360
  {
359
361
    /*
360
 
      Must clear this as we do a memcmp in optimizer/range.cc to detect
 
362
      Must clear this as we do a memcmp in opt_range.cc to detect
361
363
      identical keys
362
364
    */
363
365
    memset(buff+HA_KEY_BLOB_LENGTH+blob_length, 0, (length-blob_length));
364
 
    length=(uint32_t) blob_length;
 
366
    length=(uint) blob_length;
365
367
  }
366
368
  int2store(buff,length);
367
369
  memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
369
371
}
370
372
 
371
373
 
372
 
uint32_t Field_blob::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
373
 
{
374
 
  uint32_t blob_length= get_length(ptr);
375
 
  unsigned char *blob;
376
 
 
377
 
  get_ptr(&blob);
378
 
  uint32_t local_char_length= length / field_charset->mbmaxlen;
379
 
  local_char_length= my_charpos(field_charset, blob, blob + blob_length,
380
 
                                local_char_length);
381
 
  set_if_smaller(blob_length, local_char_length);
382
 
 
383
 
  unsigned char len_buff[HA_KEY_BLOB_LENGTH];
384
 
  int2store(len_buff,length);
385
 
  buff.append(len_buff);
386
 
  buff.append(blob, blob_length);
387
 
 
388
 
  if (length > blob_length)
389
 
  {
390
 
    /*
391
 
      Must clear this as we do a memcmp in optimizer/range.cc to detect
392
 
      identical keys
393
 
    */
394
 
 
395
 
    buff.append(length-blob_length, '0');
396
 
  }
397
 
  return HA_KEY_BLOB_LENGTH+length;
398
 
}
399
 
 
400
374
void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
401
375
{
402
376
  length= uint2korr(buff);
403
 
  (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
 
377
  (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length,
 
378
                           field_charset);
404
379
}
405
380
 
 
381
 
406
382
int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
407
383
{
408
384
  unsigned char *blob1;
409
385
  uint32_t blob_length=get_length(ptr);
410
 
  memcpy(&blob1,ptr+sizeof(uint32_t),sizeof(char*));
 
386
  memcpy(&blob1,ptr+packlength,sizeof(char*));
411
387
  const CHARSET_INFO * const cs= charset();
412
388
  uint32_t local_char_length= max_key_length / cs->mbmaxlen;
413
389
  local_char_length= my_charpos(cs, blob1, blob1+blob_length,
424
400
                         b+HA_KEY_BLOB_LENGTH, uint2korr(b));
425
401
}
426
402
 
 
403
 
 
404
/**
 
405
   Save the field metadata for blob fields.
 
406
 
 
407
   Saves the pack length in the first byte of the field metadata array
 
408
   at index of *metadata_ptr.
 
409
 
 
410
   @param   metadata_ptr   First byte of field metadata
 
411
 
 
412
   @returns number of bytes written to metadata_ptr
 
413
*/
 
414
int Field_blob::do_save_field_metadata(unsigned char *metadata_ptr)
 
415
{
 
416
  *metadata_ptr= pack_length_no_ptr();
 
417
  return 1;
 
418
}
 
419
 
 
420
 
427
421
uint32_t Field_blob::sort_length() const
428
422
{
429
 
  return (uint32_t) (getTable()->getSession()->variables.max_sort_length +
430
 
                     (field_charset == &my_charset_bin ? 0 : sizeof(uint32_t)));
 
423
  return (uint32_t) (current_session->variables.max_sort_length + 
 
424
                   (field_charset == &my_charset_bin ? 0 : packlength));
431
425
}
432
426
 
 
427
 
433
428
void Field_blob::sort_string(unsigned char *to,uint32_t length)
434
429
{
435
430
  unsigned char *blob;
446
441
      /*
447
442
        Store length of blob last in blob to shorter blobs before longer blobs
448
443
      */
449
 
      length-= sizeof(uint32_t); // size of stored blob length
 
444
      length-= packlength;
450
445
      pos= to+length;
451
446
 
452
 
      mi_int4store(pos, blob_length);
 
447
      switch (packlength) {
 
448
      case 1:
 
449
        *pos= (char) blob_length;
 
450
        break;
 
451
      case 2:
 
452
        mi_int2store(pos, blob_length);
 
453
        break;
 
454
      case 3:
 
455
        mi_int3store(pos, blob_length);
 
456
        break;
 
457
      case 4:
 
458
        mi_int4store(pos, blob_length);
 
459
        break;
 
460
      }
453
461
    }
454
 
    memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
455
 
 
 
462
    memcpy(&blob,ptr+packlength,sizeof(char*));
 
463
    
456
464
    blob_length=my_strnxfrm(field_charset,
457
465
                            to, length, blob, blob_length);
458
466
    assert(blob_length == length);
459
467
  }
460
468
}
461
469
 
462
 
uint32_t Field_blob::pack_length() const
463
 
{
464
 
  return (uint32_t) (sizeof(uint32_t) + portable_sizeof_char_ptr);
465
 
}
466
470
 
467
471
void Field_blob::sql_type(String &res) const
468
472
{
473
477
}
474
478
 
475
479
unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
476
 
                                uint32_t max_length, bool low_byte_first)
 
480
                        uint32_t max_length, bool low_byte_first)
477
481
{
478
482
  unsigned char *save= ptr;
479
483
  ptr= (unsigned char*) from;
480
 
  uint32_t length= get_length();                        // Length of from string
 
484
  uint32_t length=get_length();                 // Length of from string
481
485
 
482
486
  /*
483
487
    Store max length, which will occupy packlength bytes. If the max
484
488
    length given is smaller than the actual length of the blob, we
485
489
    just store the initial bytes of the blob.
486
490
  */
487
 
  store_length(to, min(length, max_length), low_byte_first);
 
491
  store_length(to, packlength, cmin(length, max_length), low_byte_first);
488
492
 
489
493
  /*
490
494
    Store the actual blob data, which will occupy 'length' bytes.
492
496
  if (length > 0)
493
497
  {
494
498
    get_ptr((unsigned char**) &from);
495
 
    memcpy(to+sizeof(uint32_t), from,length);
 
499
    memcpy(to+packlength, from,length);
496
500
  }
497
 
 
498
 
  ptr= save;                                    // Restore org row pointer
499
 
  return(to+sizeof(uint32_t)+length);
 
501
  ptr=save;                                     // Restore org row pointer
 
502
  return(to+packlength+length);
500
503
}
501
504
 
 
505
 
502
506
/**
503
507
   Unpack a blob field from row data.
504
508
 
505
 
   This method is used to unpack a blob field from a master whose size of
 
509
   This method is used to unpack a blob field from a master whose size of 
506
510
   the field is less than that of the slave. Note: This method is included
507
511
   to satisfy inheritance rules, but is not needed for blob fields. It
508
512
   simply is used as a pass-through to the original unpack() method for
516
520
 
517
521
   @return  New pointer into memory based on from + length of the data
518
522
*/
519
 
const unsigned char *Field_blob::unpack(unsigned char *,
520
 
                                        const unsigned char *from,
521
 
                                        uint32_t,
522
 
                                        bool low_byte_first)
 
523
const unsigned char *Field_blob::unpack(unsigned char *to __attribute__((unused)),
 
524
                                const unsigned char *from,
 
525
                                uint32_t param_data,
 
526
                                bool low_byte_first)
523
527
{
524
 
  uint32_t const length= get_length(from, low_byte_first);
525
 
  getTable()->setWriteSet(position());
526
 
  store(reinterpret_cast<const char*>(from) + sizeof(uint32_t),
 
528
  uint32_t const master_packlength=
 
529
    param_data > 0 ? param_data & 0xFF : packlength;
 
530
  uint32_t const length= get_length(from, master_packlength, low_byte_first);
 
531
  bitmap_set_bit(table->write_set, field_index);
 
532
  store(reinterpret_cast<const char*>(from) + master_packlength,
527
533
        length, field_charset);
528
 
  return(from + sizeof(uint32_t) + length);
 
534
  return(from + master_packlength + length);
 
535
}
 
536
 
 
537
/* Keys for blobs are like keys on varchars */
 
538
 
 
539
int Field_blob::pack_cmp(const unsigned char *a, const unsigned char *b, uint32_t key_length_arg,
 
540
                         bool insert_or_update)
 
541
{
 
542
  uint32_t a_length, b_length;
 
543
  if (key_length_arg > 255)
 
544
  {
 
545
    a_length=uint2korr(a); a+=2;
 
546
    b_length=uint2korr(b); b+=2;
 
547
  }
 
548
  else
 
549
  {
 
550
    a_length= (uint) *a++;
 
551
    b_length= (uint) *b++;
 
552
  }
 
553
  return field_charset->coll->strnncollsp(field_charset,
 
554
                                          a, a_length,
 
555
                                          b, b_length,
 
556
                                          insert_or_update);
 
557
}
 
558
 
 
559
 
 
560
int Field_blob::pack_cmp(const unsigned char *b, uint32_t key_length_arg,
 
561
                         bool insert_or_update)
 
562
{
 
563
  unsigned char *a;
 
564
  uint32_t a_length, b_length;
 
565
  memcpy(&a,ptr+packlength,sizeof(char*));
 
566
  if (!a)
 
567
    return key_length_arg > 0 ? -1 : 0;
 
568
 
 
569
  a_length= get_length(ptr);
 
570
  if (key_length_arg > 255)
 
571
  {
 
572
    b_length= uint2korr(b); b+=2;
 
573
  }
 
574
  else
 
575
    b_length= (uint) *b++;
 
576
  return field_charset->coll->strnncollsp(field_charset,
 
577
                                          a, a_length,
 
578
                                          b, b_length,
 
579
                                          insert_or_update);
529
580
}
530
581
 
531
582
/** Create a packed key that will be used for storage from a MySQL row. */
532
583
 
533
584
unsigned char *
534
585
Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
535
 
                     bool )
 
586
                     bool low_byte_first __attribute__((unused)))
536
587
{
537
588
  unsigned char *save= ptr;
538
589
  ptr= (unsigned char*) from;
555
606
 
556
607
 
557
608
/**
 
609
  Unpack a blob key into a record buffer.
 
610
 
 
611
  A blob key has a maximum size of 64K-1.
 
612
  In its packed form, the length field is one or two bytes long,
 
613
  depending on 'max_length'.
 
614
  Depending on the maximum length of a blob, its length field is
 
615
  put into 1 to 4 bytes. This is a property of the blob object,
 
616
  described by 'packlength'.
 
617
  Blobs are internally stored apart from the record buffer, which
 
618
  contains a pointer to the blob buffer.
 
619
 
 
620
 
 
621
  @param to                          Pointer into the record buffer.
 
622
  @param from                        Pointer to the packed key.
 
623
  @param max_length                  Key length limit from key description.
 
624
 
 
625
  @return
 
626
    Pointer into 'from' past the last byte copied from packed key.
 
627
*/
 
628
 
 
629
const unsigned char *
 
630
Field_blob::unpack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
 
631
                       bool low_byte_first __attribute__((unused)))
 
632
{
 
633
  /* get length of the blob key */
 
634
  uint32_t length= *from++;
 
635
  if (max_length > 255)
 
636
    length+= *from++ << 8;
 
637
 
 
638
  /* put the length into the record buffer */
 
639
  put_length(to, length);
 
640
 
 
641
  /* put the address of the blob buffer or NULL */
 
642
  if (length)
 
643
    memcpy(to + packlength, &from, sizeof(from));
 
644
  else
 
645
    memset(to + packlength, 0, sizeof(from));
 
646
 
 
647
  /* point to first byte of next field in 'from' */
 
648
  return from + length;
 
649
}
 
650
 
 
651
 
 
652
/** Create a packed key that will be used for storage from a MySQL key. */
 
653
 
 
654
unsigned char *
 
655
Field_blob::pack_key_from_key_image(unsigned char *to, const unsigned char *from, uint32_t max_length,
 
656
                                    bool low_byte_first __attribute__((unused)))
 
657
{
 
658
  uint32_t length=uint2korr(from);
 
659
  if (length > max_length)
 
660
    length=max_length;
 
661
  *to++= (char) (length & 255);
 
662
  if (max_length > 255)
 
663
    *to++= (char) (length >> 8);
 
664
  if (length)
 
665
    memcpy(to, from+HA_KEY_BLOB_LENGTH, length);
 
666
  return to+length;
 
667
}
 
668
 
 
669
 
 
670
uint32_t Field_blob::packed_col_length(const unsigned char *data_ptr, uint32_t length)
 
671
{
 
672
  if (length > 255)
 
673
    return uint2korr(data_ptr)+2;
 
674
  return (uint) *data_ptr + 1;
 
675
}
 
676
 
 
677
 
 
678
uint32_t Field_blob::max_packed_col_length(uint32_t max_length)
 
679
{
 
680
  return (max_length > 255 ? 2 : 1)+max_length;
 
681
}
 
682
 
 
683
 
 
684
uint32_t Field_blob::is_equal(Create_field *new_field)
 
685
{
 
686
  if (compare_str_field_flags(new_field, flags))
 
687
    return 0;
 
688
 
 
689
  return ((new_field->sql_type == get_blob_type_from_length(max_data_length()))
 
690
          && new_field->charset == field_charset &&
 
691
          ((Field_blob *)new_field->field)->max_data_length() ==
 
692
          max_data_length());
 
693
}
 
694
 
 
695
 
 
696
/**
558
697
  maximum possible display length for blob.
559
698
 
560
699
  @return
563
702
 
564
703
uint32_t Field_blob::max_display_length()
565
704
{
 
705
  switch (packlength)
 
706
  {
 
707
  case 1:
 
708
    return 255 * field_charset->mbmaxlen;
 
709
  case 2:
 
710
    return 65535 * field_charset->mbmaxlen;
 
711
  case 3:
 
712
    return 16777215 * field_charset->mbmaxlen;
 
713
  case 4:
566
714
    return (uint32_t) 4294967295U;
 
715
  default:
 
716
    assert(0); // we should never go here
 
717
    return 0;
 
718
  }
567
719
}
568
720
 
569
 
} /* namespace drizzled */