00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023 #include <drizzled/field/blob.h>
00024 #include <drizzled/table.h>
00025 #include <drizzled/session.h>
00026 #include <plugin/myisam/myisam.h>
00027
00028 #include <string>
00029 #include <algorithm>
00030
00031 using namespace std;
00032
00033 namespace drizzled
00034 {
00035
00036 static uint32_t blob_pack_length_to_max_length(uint32_t arg)
00037 {
00038 return max(UINT32_MAX,
00039 (uint32_t)((INT64_C(1) << min(arg, 4U) * 8) - INT64_C(1)));
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00049 Field_blob::Field_blob(unsigned char *ptr_arg,
00050 unsigned char *null_ptr_arg,
00051 unsigned char null_bit_arg,
00052 const char *field_name_arg,
00053 TableShare *share,
00054 const CHARSET_INFO * const cs)
00055 :Field_str(ptr_arg,
00056 blob_pack_length_to_max_length(sizeof(uint32_t)),
00057 null_ptr_arg,
00058 null_bit_arg,
00059 field_name_arg,
00060 cs)
00061 {
00062 flags|= BLOB_FLAG;
00063 share->blob_fields++;
00064
00065 }
00066
00067 void Field_blob::store_length(unsigned char *i_ptr,
00068 uint32_t i_number,
00069 bool low_byte_first)
00070 {
00071 #ifndef WORDS_BIGENDIAN
00072 (void)low_byte_first;
00073 #endif
00074
00075 #ifdef WORDS_BIGENDIAN
00076 if (low_byte_first)
00077 {
00078 int4store(i_ptr,i_number);
00079 }
00080 else
00081 #endif
00082 longstore(i_ptr,i_number);
00083 }
00084
00085
00086 void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_number)
00087 {
00088 store_length(i_ptr, i_number, getTable()->getShare()->db_low_byte_first);
00089 }
00090
00091
00092 uint32_t Field_blob::get_length(const unsigned char *pos,
00093 bool low_byte_first) const
00094 {
00095 #ifndef WORDS_BIGENDIAN
00096 (void)low_byte_first;
00097 #endif
00098 uint32_t tmp;
00099 #ifdef WORDS_BIGENDIAN
00100 if (low_byte_first)
00101 tmp=uint4korr(pos);
00102 else
00103 #endif
00104 longget(tmp,pos);
00105 return (uint32_t) tmp;
00106 }
00107
00108
00109 uint32_t Field_blob::get_packed_size(const unsigned char *ptr_arg,
00110 bool low_byte_first)
00111 {
00112 return sizeof(uint32_t) + get_length(ptr_arg, low_byte_first);
00113 }
00114
00115
00116 uint32_t Field_blob::get_length(uint32_t row_offset) const
00117 {
00118 return get_length(ptr+row_offset,
00119 getTable()->getShare()->db_low_byte_first);
00120 }
00121
00122
00123 uint32_t Field_blob::get_length(const unsigned char *ptr_arg) const
00124 {
00125 return get_length(ptr_arg, getTable()->getShare()->db_low_byte_first);
00126 }
00127
00128
00138 void Field_blob::put_length(unsigned char *pos, uint32_t length)
00139 {
00140 int4store(pos, length);
00141 }
00142
00143
00144 int Field_blob::store(const char *from,uint32_t length, const CHARSET_INFO * const cs)
00145 {
00146 uint32_t copy_length, new_length;
00147 const char *well_formed_error_pos;
00148 const char *cannot_convert_error_pos;
00149 const char *from_end_pos, *tmp;
00150 char buff[STRING_BUFFER_USUAL_SIZE];
00151 String tmpstr(buff,sizeof(buff), &my_charset_bin);
00152
00153 ASSERT_COLUMN_MARKED_FOR_WRITE;
00154
00155 if (!length)
00156 {
00157 memset(ptr, 0, Field_blob::pack_length());
00158 return 0;
00159 }
00160
00161 if (from == value.ptr())
00162 {
00163 size_t dummy_offset;
00164 if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
00165 {
00166 Field_blob::store_length(length);
00167 memmove(ptr+sizeof(uint32_t), &from, sizeof(char*));
00168 return 0;
00169 }
00170 if (tmpstr.copy(from, length, cs))
00171 goto oom_error;
00172 from= tmpstr.ptr();
00173 }
00174
00175 new_length= min(max_data_length(), field_charset->mbmaxlen * length);
00176 if (value.alloc(new_length))
00177 goto oom_error;
00178
00179
00180
00181
00182
00183
00184 copy_length= well_formed_copy_nchars(field_charset,
00185 (char*) value.ptr(), new_length,
00186 cs, from, length,
00187 length,
00188 &well_formed_error_pos,
00189 &cannot_convert_error_pos,
00190 &from_end_pos);
00191
00192 Field_blob::store_length(copy_length);
00193 tmp= value.ptr();
00194 memmove(ptr+sizeof(uint32_t), &tmp, sizeof(char*));
00195
00196 if (check_string_copy_error(this, well_formed_error_pos,
00197 cannot_convert_error_pos, from + length, cs))
00198 return 2;
00199
00200 return report_if_important_data(from_end_pos, from + length);
00201
00202 oom_error:
00203
00204 memset(ptr, 0, Field_blob::pack_length());
00205 return -1;
00206 }
00207
00208
00209 int Field_blob::store(double nr)
00210 {
00211 const CHARSET_INFO * const cs=charset();
00212 ASSERT_COLUMN_MARKED_FOR_WRITE;
00213 value.set_real(nr, NOT_FIXED_DEC, cs);
00214 return Field_blob::store(value.ptr(),(uint32_t) value.length(), cs);
00215 }
00216
00217
00218 int Field_blob::store(int64_t nr, bool unsigned_val)
00219 {
00220 const CHARSET_INFO * const cs=charset();
00221 ASSERT_COLUMN_MARKED_FOR_WRITE;
00222 value.set_int(nr, unsigned_val, cs);
00223 return Field_blob::store(value.ptr(), (uint32_t) value.length(), cs);
00224 }
00225
00226
00227 double Field_blob::val_real(void) const
00228 {
00229 int not_used;
00230 char *end_not_used, *blob;
00231 uint32_t length;
00232 const CHARSET_INFO *cs;
00233
00234 ASSERT_COLUMN_MARKED_FOR_READ;
00235
00236 memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
00237 if (!blob)
00238 return 0.0;
00239 length= get_length(ptr);
00240 cs= charset();
00241 return my_strntod(cs, blob, length, &end_not_used, ¬_used);
00242 }
00243
00244
00245 int64_t Field_blob::val_int(void) const
00246 {
00247 int not_used;
00248 char *blob;
00249
00250 ASSERT_COLUMN_MARKED_FOR_READ;
00251
00252 memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
00253 if (!blob)
00254 return 0;
00255 uint32_t length= get_length(ptr);
00256 return my_strntoll(charset(),blob,length,10,NULL,¬_used);
00257 }
00258
00259 String *Field_blob::val_str(String *, String *val_ptr) const
00260 {
00261 char *blob;
00262
00263 ASSERT_COLUMN_MARKED_FOR_READ;
00264
00265 memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
00266 if (!blob)
00267 val_ptr->set("",0,charset());
00268 else
00269 val_ptr->set((const char*) blob,get_length(ptr),charset());
00270 return val_ptr;
00271 }
00272
00273
00274 type::Decimal *Field_blob::val_decimal(type::Decimal *decimal_value) const
00275 {
00276 const char *blob;
00277 size_t length;
00278
00279 ASSERT_COLUMN_MARKED_FOR_READ;
00280
00281 memcpy(&blob, ptr+sizeof(uint32_t), sizeof(const unsigned char*));
00282 if (!blob)
00283 {
00284 blob= "";
00285 length= 0;
00286 }
00287 else
00288 {
00289 length= get_length(ptr);
00290 }
00291
00292 decimal_value->store(E_DEC_FATAL_ERROR, blob, length, charset());
00293
00294 return decimal_value;
00295 }
00296
00297
00298 int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
00299 uint32_t b_length)
00300 {
00301 return field_charset->coll->strnncollsp(field_charset,
00302 a, a_length, b, b_length,
00303 0);
00304 }
00305
00306
00307 int Field_blob::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
00308 uint32_t max_length)
00309 {
00310 unsigned char *blob1,*blob2;
00311 memcpy(&blob1,a_ptr+sizeof(uint32_t),sizeof(char*));
00312 memcpy(&blob2,b_ptr+sizeof(uint32_t),sizeof(char*));
00313 uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
00314 set_if_smaller(a_len, max_length);
00315 set_if_smaller(b_len, max_length);
00316 return Field_blob::cmp(blob1,a_len,blob2,b_len);
00317 }
00318
00319
00320 int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
00321 uint32_t max_length)
00322 {
00323 char *a,*b;
00324 uint32_t diff;
00325 uint32_t a_length,b_length;
00326 memcpy(&a,a_ptr+sizeof(uint32_t),sizeof(char*));
00327 memcpy(&b,b_ptr+sizeof(uint32_t),sizeof(char*));
00328
00329 a_length= get_length(a_ptr);
00330
00331 if (a_length > max_length)
00332 a_length= max_length;
00333
00334 b_length= get_length(b_ptr);
00335
00336 if (b_length > max_length)
00337 b_length= max_length;
00338
00339 diff= memcmp(a,b,min(a_length,b_length));
00340
00341 return diff ? diff : (unsigned int) (a_length - b_length);
00342 }
00343
00344
00345 uint32_t Field_blob::get_key_image(unsigned char *buff, uint32_t length)
00346 {
00347 uint32_t blob_length= get_length(ptr);
00348 unsigned char *blob;
00349
00350 get_ptr(&blob);
00351 uint32_t local_char_length= length / field_charset->mbmaxlen;
00352 local_char_length= my_charpos(field_charset, blob, blob + blob_length,
00353 local_char_length);
00354 set_if_smaller(blob_length, local_char_length);
00355
00356 if ((uint32_t) length > blob_length)
00357 {
00358
00359
00360
00361
00362 memset(buff+HA_KEY_BLOB_LENGTH+blob_length, 0, (length-blob_length));
00363 length=(uint32_t) blob_length;
00364 }
00365 int2store(buff,length);
00366 memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
00367 return HA_KEY_BLOB_LENGTH+length;
00368 }
00369
00370
00371 uint32_t Field_blob::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
00372 {
00373 uint32_t blob_length= get_length(ptr);
00374 unsigned char *blob;
00375
00376 get_ptr(&blob);
00377 uint32_t local_char_length= length / field_charset->mbmaxlen;
00378 local_char_length= my_charpos(field_charset, blob, blob + blob_length,
00379 local_char_length);
00380 set_if_smaller(blob_length, local_char_length);
00381
00382 unsigned char len_buff[HA_KEY_BLOB_LENGTH];
00383 int2store(len_buff,length);
00384 buff.append(len_buff);
00385 buff.append(blob, blob_length);
00386
00387 if (length > blob_length)
00388 {
00389
00390
00391
00392
00393
00394 buff.append(length-blob_length, '0');
00395 }
00396 return HA_KEY_BLOB_LENGTH+length;
00397 }
00398
00399 void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
00400 {
00401 length= uint2korr(buff);
00402 (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
00403 }
00404
00405 int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
00406 {
00407 unsigned char *blob1;
00408 uint32_t blob_length=get_length(ptr);
00409 memcpy(&blob1,ptr+sizeof(uint32_t),sizeof(char*));
00410 const CHARSET_INFO * const cs= charset();
00411 uint32_t local_char_length= max_key_length / cs->mbmaxlen;
00412 local_char_length= my_charpos(cs, blob1, blob1+blob_length,
00413 local_char_length);
00414 set_if_smaller(blob_length, local_char_length);
00415 return Field_blob::cmp(blob1, blob_length,
00416 key_ptr+HA_KEY_BLOB_LENGTH,
00417 uint2korr(key_ptr));
00418 }
00419
00420 int Field_blob::key_cmp(const unsigned char *a,const unsigned char *b)
00421 {
00422 return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
00423 b+HA_KEY_BLOB_LENGTH, uint2korr(b));
00424 }
00425
00426 uint32_t Field_blob::sort_length() const
00427 {
00428 return (uint32_t) (getTable()->getSession()->variables.max_sort_length +
00429 (field_charset == &my_charset_bin ? 0 : sizeof(uint32_t)));
00430 }
00431
00432 void Field_blob::sort_string(unsigned char *to,uint32_t length)
00433 {
00434 unsigned char *blob;
00435 uint32_t blob_length=get_length();
00436
00437 if (!blob_length)
00438 memset(to, 0, length);
00439 else
00440 {
00441 if (field_charset == &my_charset_bin)
00442 {
00443 unsigned char *pos;
00444
00445
00446
00447
00448 length-= sizeof(uint32_t);
00449 pos= to+length;
00450
00451 mi_int4store(pos, blob_length);
00452 }
00453 memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
00454
00455 blob_length=my_strnxfrm(field_charset,
00456 to, length, blob, blob_length);
00457 assert(blob_length == length);
00458 }
00459 }
00460
00461 uint32_t Field_blob::pack_length() const
00462 {
00463 return (uint32_t) (sizeof(uint32_t) + portable_sizeof_char_ptr);
00464 }
00465
00466 void Field_blob::sql_type(String &res) const
00467 {
00468 if (charset() == &my_charset_bin)
00469 res.set_ascii(STRING_WITH_LEN("blob"));
00470 else
00471 res.set_ascii(STRING_WITH_LEN("text"));
00472 }
00473
00474 unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
00475 uint32_t max_length, bool low_byte_first)
00476 {
00477 unsigned char *save= ptr;
00478 ptr= (unsigned char*) from;
00479 uint32_t length= get_length();
00480
00481
00482
00483
00484
00485
00486 store_length(to, min(length, max_length), low_byte_first);
00487
00488
00489
00490
00491 if (length > 0)
00492 {
00493 get_ptr((unsigned char**) &from);
00494 memcpy(to+sizeof(uint32_t), from,length);
00495 }
00496
00497 ptr= save;
00498 return(to+sizeof(uint32_t)+length);
00499 }
00500
00518 const unsigned char *Field_blob::unpack(unsigned char *,
00519 const unsigned char *from,
00520 uint32_t,
00521 bool low_byte_first)
00522 {
00523 uint32_t const length= get_length(from, low_byte_first);
00524 getTable()->setWriteSet(position());
00525 store(reinterpret_cast<const char*>(from) + sizeof(uint32_t),
00526 length, field_charset);
00527 return(from + sizeof(uint32_t) + length);
00528 }
00529
00532 unsigned char *
00533 Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
00534 bool )
00535 {
00536 unsigned char *save= ptr;
00537 ptr= (unsigned char*) from;
00538 uint32_t length=get_length();
00539 uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
00540 max_length/field_charset->mbmaxlen : max_length);
00541 if (length)
00542 get_ptr((unsigned char**) &from);
00543 if (length > local_char_length)
00544 local_char_length= my_charpos(field_charset, from, from+length,
00545 local_char_length);
00546 set_if_smaller(length, local_char_length);
00547 *to++= (unsigned char) length;
00548 if (max_length > 255)
00549 *to++= (unsigned char) (length >> 8);
00550 memcpy(to, from, length);
00551 ptr=save;
00552 return to+length;
00553 }
00554
00555
00563 uint32_t Field_blob::max_display_length()
00564 {
00565 return (uint32_t) 4294967295U;
00566 }
00567
00568 }