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,
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)
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)
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)
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)
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 *,
264
ASSERT_COLUMN_MARKED_FOR_READ;
266
memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
268
val_ptr->set("",0,charset()); // A bit safer than ->length(0)
270
val_ptr->set((const char*) blob,get_length(ptr),charset());
275
my_decimal *Field_blob::val_decimal(my_decimal *decimal_value)
280
ASSERT_COLUMN_MARKED_FOR_READ;
282
memcpy(&blob, ptr+sizeof(uint32_t), sizeof(const unsigned char*));
289
length= get_length(ptr);
291
str2my_decimal(E_DEC_FATAL_ERROR, blob, length, charset(),
293
return decimal_value;
297
int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
300
return field_charset->coll->strnncollsp(field_charset,
301
a, a_length, b, b_length,
306
int Field_blob::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
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);
313
set_if_smaller(a_len, max_length);
314
set_if_smaller(b_len, max_length);
315
return Field_blob::cmp(blob1,a_len,blob2,b_len);
319
int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
324
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*));
328
a_length= get_length(a_ptr);
330
if (a_length > max_length)
331
a_length= max_length;
333
b_length= get_length(b_ptr);
335
if (b_length > max_length)
336
b_length= max_length;
338
diff= memcmp(a,b,min(a_length,b_length));
340
return diff ? diff : (unsigned int) (a_length - b_length);
343
/* The following is used only when comparing a key */
344
uint32_t Field_blob::get_key_image(unsigned char *buff, uint32_t length)
346
uint32_t blob_length= get_length(ptr);
350
uint32_t local_char_length= length / field_charset->mbmaxlen;
351
local_char_length= my_charpos(field_charset, blob, blob + blob_length,
353
set_if_smaller(blob_length, local_char_length);
355
if ((uint32_t) length > blob_length)
358
Must clear this as we do a memcmp in optimizer/range.cc to detect
361
memset(buff+HA_KEY_BLOB_LENGTH+blob_length, 0, (length-blob_length));
362
length=(uint32_t) blob_length;
364
int2store(buff,length);
365
memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
366
return HA_KEY_BLOB_LENGTH+length;
370
uint32_t Field_blob::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
372
uint32_t blob_length= get_length(ptr);
376
uint32_t local_char_length= length / field_charset->mbmaxlen;
377
local_char_length= my_charpos(field_charset, blob, blob + blob_length,
379
set_if_smaller(blob_length, local_char_length);
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);
386
if (length > blob_length)
389
Must clear this as we do a memcmp in optimizer/range.cc to detect
393
buff.append(length-blob_length, '0');
395
return HA_KEY_BLOB_LENGTH+length;
398
void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
400
length= uint2korr(buff);
401
(void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
404
int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
406
unsigned char *blob1;
407
uint32_t blob_length=get_length(ptr);
408
memcpy(&blob1,ptr+sizeof(uint32_t),sizeof(char*));
409
const CHARSET_INFO * const cs= charset();
410
uint32_t local_char_length= max_key_length / cs->mbmaxlen;
411
local_char_length= my_charpos(cs, blob1, blob1+blob_length,
413
set_if_smaller(blob_length, local_char_length);
414
return Field_blob::cmp(blob1, blob_length,
415
key_ptr+HA_KEY_BLOB_LENGTH,
419
int Field_blob::key_cmp(const unsigned char *a,const unsigned char *b)
421
return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
422
b+HA_KEY_BLOB_LENGTH, uint2korr(b));
425
uint32_t Field_blob::sort_length() const
427
return (uint32_t) (current_session->variables.max_sort_length +
428
(field_charset == &my_charset_bin ? 0 : sizeof(uint32_t)));
431
void Field_blob::sort_string(unsigned char *to,uint32_t length)
434
uint32_t blob_length=get_length();
437
memset(to, 0, length);
440
if (field_charset == &my_charset_bin)
445
Store length of blob last in blob to shorter blobs before longer blobs
447
length-= sizeof(uint32_t); // size of stored blob length
450
mi_int4store(pos, blob_length);
452
memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
454
blob_length=my_strnxfrm(field_charset,
455
to, length, blob, blob_length);
456
assert(blob_length == length);
460
uint32_t Field_blob::pack_length() const
462
return (uint32_t) (sizeof(uint32_t) + portable_sizeof_char_ptr);
465
void Field_blob::sql_type(String &res) const
467
if (charset() == &my_charset_bin)
468
res.set_ascii(STRING_WITH_LEN("blob"));
470
res.set_ascii(STRING_WITH_LEN("text"));
473
unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
474
uint32_t max_length, bool low_byte_first)
476
unsigned char *save= ptr;
477
ptr= (unsigned char*) from;
478
uint32_t length= get_length(); // Length of from string
481
Store max length, which will occupy packlength bytes. If the max
482
length given is smaller than the actual length of the blob, we
483
just store the initial bytes of the blob.
485
store_length(to, min(length, max_length), low_byte_first);
488
Store the actual blob data, which will occupy 'length' bytes.
492
get_ptr((unsigned char**) &from);
493
memcpy(to+sizeof(uint32_t), from,length);
496
ptr= save; // Restore org row pointer
497
return(to+sizeof(uint32_t)+length);
501
Unpack a blob field from row data.
503
This method is used to unpack a blob field from a master whose size of
504
the field is less than that of the slave. Note: This method is included
505
to satisfy inheritance rules, but is not needed for blob fields. It
506
simply is used as a pass-through to the original unpack() method for
509
@param to Destination of the data
510
@param from Source of the data
511
@param param_data @c true if base types should be stored in little-
512
endian format, @c false if native format should
515
@return New pointer into memory based on from + length of the data
517
const unsigned char *Field_blob::unpack(unsigned char *,
518
const unsigned char *from,
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),
525
length, field_charset);
526
return(from + sizeof(uint32_t) + length);
529
/** Create a packed key that will be used for storage from a MySQL row. */
532
Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
535
unsigned char *save= ptr;
536
ptr= (unsigned char*) from;
537
uint32_t length=get_length(); // Length of from string
538
uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
539
max_length/field_charset->mbmaxlen : max_length);
541
get_ptr((unsigned char**) &from);
542
if (length > local_char_length)
543
local_char_length= my_charpos(field_charset, from, from+length,
545
set_if_smaller(length, local_char_length);
546
*to++= (unsigned char) length;
547
if (max_length > 255) // 2 byte length
548
*to++= (unsigned char) (length >> 8);
549
memcpy(to, from, length);
550
ptr=save; // Restore org row pointer
556
maximum possible display length for blob.
562
uint32_t Field_blob::max_display_length()
564
return (uint32_t) 4294967295U;
567
} /* namespace drizzled */