1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 MySQL
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
#include <drizzled/field/blob.h>
24
#include <drizzled/table.h>
25
#include <drizzled/session.h>
26
#include <plugin/myisam/myisam.h>
36
static uint32_t blob_pack_length_to_max_length(uint32_t arg)
38
return max(UINT32_MAX,
39
(uint32_t)((INT64_C(1) << min(arg, 4U) * 8) - INT64_C(1)));
43
/****************************************************************************
45
** 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)
47
****************************************************************************/
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,
54
const CHARSET_INFO * const cs)
56
blob_pack_length_to_max_length(sizeof(uint32_t)),
64
/* TODO: why do not fill table->getShare()->blob_field array here? */
67
void Field_blob::store_length(unsigned char *i_ptr,
71
#ifndef WORDS_BIGENDIAN
75
#ifdef WORDS_BIGENDIAN
78
int4store(i_ptr,i_number);
82
longstore(i_ptr,i_number);
86
void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_number)
88
store_length(i_ptr, i_number, getTable()->getShare()->db_low_byte_first);
92
uint32_t Field_blob::get_length(const unsigned char *pos,
93
bool low_byte_first) const
95
#ifndef WORDS_BIGENDIAN
99
#ifdef WORDS_BIGENDIAN
105
return (uint32_t) tmp;
109
uint32_t Field_blob::get_packed_size(const unsigned char *ptr_arg,
112
return sizeof(uint32_t) + get_length(ptr_arg, low_byte_first);
116
uint32_t Field_blob::get_length(uint32_t row_offset) const
118
return get_length(ptr+row_offset,
119
getTable()->getShare()->db_low_byte_first);
123
uint32_t Field_blob::get_length(const unsigned char *ptr_arg) const
125
return get_length(ptr_arg, getTable()->getShare()->db_low_byte_first);
130
Put a blob length field into a record buffer.
132
Blob length is always stored in sizeof(uint32_t) (4 bytes)
134
@param pos Pointer into the record buffer.
135
@param length The length value to put.
138
void Field_blob::put_length(unsigned char *pos, uint32_t length)
140
int4store(pos, length);
144
int Field_blob::store(const char *from,uint32_t length, const CHARSET_INFO * const cs)
146
uint32_t copy_length, new_length;
147
const char *well_formed_error_pos;
148
const char *cannot_convert_error_pos;
149
const char *from_end_pos, *tmp;
150
char buff[STRING_BUFFER_USUAL_SIZE];
151
String tmpstr(buff,sizeof(buff), &my_charset_bin);
153
ASSERT_COLUMN_MARKED_FOR_WRITE;
157
memset(ptr, 0, Field_blob::pack_length());
161
if (from == value.ptr())
164
if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
166
Field_blob::store_length(length);
167
memmove(ptr+sizeof(uint32_t), &from, sizeof(char*));
170
if (tmpstr.copy(from, length, cs))
175
new_length= min(max_data_length(), field_charset->mbmaxlen * length);
176
if (value.alloc(new_length))
180
"length" is OK as "nchars" argument to well_formed_copy_nchars as this
181
is never used to limit the length of the data. The cut of long data
182
is done with the new_length value.
184
copy_length= well_formed_copy_nchars(field_charset,
185
(char*) value.ptr(), new_length,
188
&well_formed_error_pos,
189
&cannot_convert_error_pos,
192
Field_blob::store_length(copy_length);
194
memmove(ptr+sizeof(uint32_t), &tmp, sizeof(char*));
196
if (check_string_copy_error(this, well_formed_error_pos,
197
cannot_convert_error_pos, from + length, cs))
200
return report_if_important_data(from_end_pos, from + length);
203
/* Fatal OOM error */
204
memset(ptr, 0, Field_blob::pack_length());
209
int Field_blob::store(double nr)
211
const CHARSET_INFO * const cs=charset();
212
ASSERT_COLUMN_MARKED_FOR_WRITE;
213
value.set_real(nr, NOT_FIXED_DEC, cs);
214
return Field_blob::store(value.ptr(),(uint32_t) value.length(), cs);
218
int Field_blob::store(int64_t nr, bool unsigned_val)
220
const CHARSET_INFO * const cs=charset();
221
ASSERT_COLUMN_MARKED_FOR_WRITE;
222
value.set_int(nr, unsigned_val, cs);
223
return Field_blob::store(value.ptr(), (uint32_t) value.length(), cs);
227
double Field_blob::val_real(void) const
230
char *end_not_used, *blob;
232
const CHARSET_INFO *cs;
234
ASSERT_COLUMN_MARKED_FOR_READ;
236
memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
239
length= get_length(ptr);
241
return my_strntod(cs, blob, length, &end_not_used, ¬_used);
245
int64_t Field_blob::val_int(void) const
250
ASSERT_COLUMN_MARKED_FOR_READ;
252
memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
255
uint32_t length= get_length(ptr);
256
return my_strntoll(charset(),blob,length,10,NULL,¬_used);
259
String *Field_blob::val_str(String *, String *val_ptr) const
263
ASSERT_COLUMN_MARKED_FOR_READ;
265
memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
267
val_ptr->set("",0,charset()); // A bit safer than ->length(0)
269
val_ptr->set((const char*) blob,get_length(ptr),charset());
274
type::Decimal *Field_blob::val_decimal(type::Decimal *decimal_value) const
279
ASSERT_COLUMN_MARKED_FOR_READ;
281
memcpy(&blob, ptr+sizeof(uint32_t), sizeof(const unsigned char*));
289
length= get_length(ptr);
292
decimal_value->store(E_DEC_FATAL_ERROR, blob, length, charset());
294
return decimal_value;
298
int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
301
return field_charset->coll->strnncollsp(field_charset,
302
a, a_length, b, b_length,
307
int Field_blob::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
310
unsigned char *blob1,*blob2;
311
memcpy(&blob1,a_ptr+sizeof(uint32_t),sizeof(char*));
312
memcpy(&blob2,b_ptr+sizeof(uint32_t),sizeof(char*));
313
uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
314
set_if_smaller(a_len, max_length);
315
set_if_smaller(b_len, max_length);
316
return Field_blob::cmp(blob1,a_len,blob2,b_len);
320
int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
325
uint32_t a_length,b_length;
326
memcpy(&a,a_ptr+sizeof(uint32_t),sizeof(char*));
327
memcpy(&b,b_ptr+sizeof(uint32_t),sizeof(char*));
329
a_length= get_length(a_ptr);
331
if (a_length > max_length)
332
a_length= max_length;
334
b_length= get_length(b_ptr);
336
if (b_length > max_length)
337
b_length= max_length;
339
diff= memcmp(a,b,min(a_length,b_length));
341
return diff ? diff : (unsigned int) (a_length - b_length);
344
/* The following is used only when comparing a key */
345
uint32_t Field_blob::get_key_image(unsigned char *buff, uint32_t length)
347
uint32_t blob_length= get_length(ptr);
351
uint32_t local_char_length= length / field_charset->mbmaxlen;
352
local_char_length= my_charpos(field_charset, blob, blob + blob_length,
354
set_if_smaller(blob_length, local_char_length);
356
if ((uint32_t) length > blob_length)
359
Must clear this as we do a memcmp in optimizer/range.cc to detect
362
memset(buff+HA_KEY_BLOB_LENGTH+blob_length, 0, (length-blob_length));
363
length=(uint32_t) blob_length;
365
int2store(buff,length);
366
memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
367
return HA_KEY_BLOB_LENGTH+length;
371
uint32_t Field_blob::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
373
uint32_t blob_length= get_length(ptr);
377
uint32_t local_char_length= length / field_charset->mbmaxlen;
378
local_char_length= my_charpos(field_charset, blob, blob + blob_length,
380
set_if_smaller(blob_length, local_char_length);
382
unsigned char len_buff[HA_KEY_BLOB_LENGTH];
383
int2store(len_buff,length);
384
buff.append(len_buff);
385
buff.append(blob, blob_length);
387
if (length > blob_length)
390
Must clear this as we do a memcmp in optimizer/range.cc to detect
394
buff.append(length-blob_length, '0');
396
return HA_KEY_BLOB_LENGTH+length;
399
void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
401
length= uint2korr(buff);
402
(void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
405
int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
407
unsigned char *blob1;
408
uint32_t blob_length=get_length(ptr);
409
memcpy(&blob1,ptr+sizeof(uint32_t),sizeof(char*));
410
const CHARSET_INFO * const cs= charset();
411
uint32_t local_char_length= max_key_length / cs->mbmaxlen;
412
local_char_length= my_charpos(cs, blob1, blob1+blob_length,
414
set_if_smaller(blob_length, local_char_length);
415
return Field_blob::cmp(blob1, blob_length,
416
key_ptr+HA_KEY_BLOB_LENGTH,
420
int Field_blob::key_cmp(const unsigned char *a,const unsigned char *b)
422
return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
423
b+HA_KEY_BLOB_LENGTH, uint2korr(b));
426
uint32_t Field_blob::sort_length() const
428
return (uint32_t) (getTable()->getSession()->variables.max_sort_length +
429
(field_charset == &my_charset_bin ? 0 : sizeof(uint32_t)));
432
void Field_blob::sort_string(unsigned char *to,uint32_t length)
435
uint32_t blob_length=get_length();
438
memset(to, 0, length);
441
if (field_charset == &my_charset_bin)
446
Store length of blob last in blob to shorter blobs before longer blobs
448
length-= sizeof(uint32_t); // size of stored blob length
451
mi_int4store(pos, blob_length);
453
memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
455
blob_length=my_strnxfrm(field_charset,
456
to, length, blob, blob_length);
457
assert(blob_length == length);
461
uint32_t Field_blob::pack_length() const
463
return (uint32_t) (sizeof(uint32_t) + portable_sizeof_char_ptr);
466
void Field_blob::sql_type(String &res) const
468
if (charset() == &my_charset_bin)
469
res.set_ascii(STRING_WITH_LEN("blob"));
471
res.set_ascii(STRING_WITH_LEN("text"));
474
unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
475
uint32_t max_length, bool low_byte_first)
477
unsigned char *save= ptr;
478
ptr= (unsigned char*) from;
479
uint32_t length= get_length(); // Length of from string
482
Store max length, which will occupy packlength bytes. If the max
483
length given is smaller than the actual length of the blob, we
484
just store the initial bytes of the blob.
486
store_length(to, min(length, max_length), low_byte_first);
489
Store the actual blob data, which will occupy 'length' bytes.
493
get_ptr((unsigned char**) &from);
494
memcpy(to+sizeof(uint32_t), from,length);
497
ptr= save; // Restore org row pointer
498
return(to+sizeof(uint32_t)+length);
502
Unpack a blob field from row data.
504
This method is used to unpack a blob field from a master whose size of
505
the field is less than that of the slave. Note: This method is included
506
to satisfy inheritance rules, but is not needed for blob fields. It
507
simply is used as a pass-through to the original unpack() method for
510
@param to Destination of the data
511
@param from Source of the data
512
@param param_data @c true if base types should be stored in little-
513
endian format, @c false if native format should
516
@return New pointer into memory based on from + length of the data
518
const unsigned char *Field_blob::unpack(unsigned char *,
519
const unsigned char *from,
523
uint32_t const length= get_length(from, low_byte_first);
524
getTable()->setWriteSet(position());
525
store(reinterpret_cast<const char*>(from) + sizeof(uint32_t),
526
length, field_charset);
527
return(from + sizeof(uint32_t) + length);
530
/** Create a packed key that will be used for storage from a MySQL row. */
533
Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
536
unsigned char *save= ptr;
537
ptr= (unsigned char*) from;
538
uint32_t length=get_length(); // Length of from string
539
uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
540
max_length/field_charset->mbmaxlen : max_length);
542
get_ptr((unsigned char**) &from);
543
if (length > local_char_length)
544
local_char_length= my_charpos(field_charset, from, from+length,
546
set_if_smaller(length, local_char_length);
547
*to++= (unsigned char) length;
548
if (max_length > 255) // 2 byte length
549
*to++= (unsigned char) (length >> 8);
550
memcpy(to, from, length);
551
ptr=save; // Restore org row pointer
557
maximum possible display length for blob.
563
uint32_t Field_blob::max_display_length()
565
return (uint32_t) 4294967295U;
568
} /* namespace drizzled */