~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.cc

  • Committer: Mark Atwood
  • Date: 2008-10-03 01:39:40 UTC
  • mto: This revision was merged to the branch mainline in revision 437.
  • Revision ID: mark@fallenpegasus.com-20081003013940-mvefjo725dltz41h
rename logging_noop to logging_query

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