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 #include <drizzled/system_variables.h>
00028
00029 #include <string>
00030 #include <algorithm>
00031
00032 using namespace std;
00033
00034 namespace drizzled {
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_st * 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_st * 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 if (!String::needs_conversion(length, cs, field_charset))
00164 {
00165 Field_blob::store_length(length);
00166 memmove(ptr+sizeof(uint32_t), &from, sizeof(char*));
00167 return 0;
00168 }
00169 tmpstr.copy(from, length, cs);
00170 from= tmpstr.ptr();
00171 }
00172
00173 new_length= min(max_data_length(), field_charset->mbmaxlen * length);
00174 value.alloc(new_length);
00175
00176
00177
00178
00179
00180
00181 copy_length= well_formed_copy_nchars(field_charset,
00182 (char*) value.ptr(), new_length,
00183 cs, from, length,
00184 length,
00185 &well_formed_error_pos,
00186 &cannot_convert_error_pos,
00187 &from_end_pos);
00188
00189 Field_blob::store_length(copy_length);
00190 tmp= value.ptr();
00191 memmove(ptr+sizeof(uint32_t), &tmp, sizeof(char*));
00192
00193 if (check_string_copy_error(this, well_formed_error_pos,
00194 cannot_convert_error_pos, from + length, cs))
00195 return 2;
00196
00197 return report_if_important_data(from_end_pos, from + length);
00198 }
00199
00200 int Field_blob::store(double nr)
00201 {
00202 const charset_info_st * const cs=charset();
00203 ASSERT_COLUMN_MARKED_FOR_WRITE;
00204 value.set_real(nr, NOT_FIXED_DEC, cs);
00205 return Field_blob::store(value.ptr(),(uint32_t) value.length(), cs);
00206 }
00207
00208 int Field_blob::store(int64_t nr, bool unsigned_val)
00209 {
00210 const charset_info_st * const cs=charset();
00211 ASSERT_COLUMN_MARKED_FOR_WRITE;
00212 value.set_int(nr, unsigned_val, cs);
00213 return Field_blob::store(value.ptr(), (uint32_t) value.length(), cs);
00214 }
00215
00216
00217 double Field_blob::val_real(void) const
00218 {
00219 int not_used;
00220 char *end_not_used, *blob;
00221 uint32_t length;
00222 const charset_info_st *cs;
00223
00224 ASSERT_COLUMN_MARKED_FOR_READ;
00225
00226 memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
00227 if (!blob)
00228 return 0.0;
00229 length= get_length(ptr);
00230 cs= charset();
00231 return my_strntod(cs, blob, length, &end_not_used, ¬_used);
00232 }
00233
00234
00235 int64_t Field_blob::val_int(void) const
00236 {
00237 int not_used;
00238 char *blob;
00239
00240 ASSERT_COLUMN_MARKED_FOR_READ;
00241
00242 memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
00243 if (!blob)
00244 return 0;
00245 uint32_t length= get_length(ptr);
00246 return my_strntoll(charset(),blob,length,10,NULL,¬_used);
00247 }
00248
00249 String *Field_blob::val_str(String *, String *val_ptr) const
00250 {
00251 char *blob;
00252
00253 ASSERT_COLUMN_MARKED_FOR_READ;
00254
00255 memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
00256 if (!blob)
00257 val_ptr->set("",0,charset());
00258 else
00259 val_ptr->set(blob,get_length(ptr),charset());
00260 return val_ptr;
00261 }
00262
00263
00264 type::Decimal *Field_blob::val_decimal(type::Decimal *decimal_value) const
00265 {
00266 const char *blob;
00267 size_t length;
00268
00269 ASSERT_COLUMN_MARKED_FOR_READ;
00270
00271 memcpy(&blob, ptr+sizeof(uint32_t), sizeof(const unsigned char*));
00272 if (!blob)
00273 {
00274 blob= "";
00275 length= 0;
00276 }
00277 else
00278 {
00279 length= get_length(ptr);
00280 }
00281
00282 decimal_value->store(E_DEC_FATAL_ERROR, blob, length, charset());
00283
00284 return decimal_value;
00285 }
00286
00287
00288 int Field_blob::cmp(const unsigned char *a,uint32_t a_length, const unsigned char *b,
00289 uint32_t b_length)
00290 {
00291 return field_charset->coll->strnncollsp(field_charset,
00292 a, a_length, b, b_length,
00293 0);
00294 }
00295
00296
00297 int Field_blob::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
00298 uint32_t max_length)
00299 {
00300 unsigned char *blob1,*blob2;
00301 memcpy(&blob1,a_ptr+sizeof(uint32_t),sizeof(char*));
00302 memcpy(&blob2,b_ptr+sizeof(uint32_t),sizeof(char*));
00303 uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
00304 set_if_smaller(a_len, max_length);
00305 set_if_smaller(b_len, max_length);
00306 return Field_blob::cmp(blob1,a_len,blob2,b_len);
00307 }
00308
00309
00310 int Field_blob::cmp_binary(const unsigned char *a_ptr, const unsigned char *b_ptr,
00311 uint32_t max_length)
00312 {
00313 char *a,*b;
00314 uint32_t diff;
00315 uint32_t a_length,b_length;
00316 memcpy(&a,a_ptr+sizeof(uint32_t),sizeof(char*));
00317 memcpy(&b,b_ptr+sizeof(uint32_t),sizeof(char*));
00318
00319 a_length= get_length(a_ptr);
00320
00321 if (a_length > max_length)
00322 a_length= max_length;
00323
00324 b_length= get_length(b_ptr);
00325
00326 if (b_length > max_length)
00327 b_length= max_length;
00328
00329 diff= memcmp(a,b,min(a_length,b_length));
00330
00331 return diff ? diff : (unsigned int) (a_length - b_length);
00332 }
00333
00334
00335 uint32_t Field_blob::get_key_image(unsigned char *buff, uint32_t length)
00336 {
00337 uint32_t blob_length= get_length(ptr);
00338 unsigned char *blob= get_ptr();
00339 uint32_t local_char_length= length / field_charset->mbmaxlen;
00340 local_char_length= my_charpos(field_charset, blob, blob + blob_length,
00341 local_char_length);
00342 set_if_smaller(blob_length, local_char_length);
00343
00344 if ((uint32_t) length > blob_length)
00345 {
00346
00347
00348
00349
00350 memset(buff+HA_KEY_BLOB_LENGTH+blob_length, 0, (length-blob_length));
00351 length=(uint32_t) blob_length;
00352 }
00353 int2store(buff,length);
00354 memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
00355 return HA_KEY_BLOB_LENGTH+length;
00356 }
00357
00358 uint32_t Field_blob::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
00359 {
00360 uint32_t blob_length= get_length(ptr);
00361 unsigned char* blob= get_ptr();
00362 uint32_t local_char_length= length / field_charset->mbmaxlen;
00363 local_char_length= my_charpos(field_charset, blob, blob + blob_length,
00364 local_char_length);
00365 set_if_smaller(blob_length, local_char_length);
00366
00367 unsigned char len_buff[HA_KEY_BLOB_LENGTH];
00368 int2store(len_buff,length);
00369 buff.append(len_buff);
00370 buff.append(blob, blob_length);
00371
00372 if (length > blob_length)
00373 {
00374
00375
00376
00377
00378
00379 buff.append(length-blob_length, '0');
00380 }
00381 return HA_KEY_BLOB_LENGTH+length;
00382 }
00383
00384 void Field_blob::set_key_image(const unsigned char *buff,uint32_t length)
00385 {
00386 length= uint2korr(buff);
00387 (void) Field_blob::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
00388 }
00389
00390 int Field_blob::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
00391 {
00392 unsigned char *blob1;
00393 uint32_t blob_length=get_length(ptr);
00394 memcpy(&blob1,ptr+sizeof(uint32_t),sizeof(char*));
00395 const charset_info_st * const cs= charset();
00396 uint32_t local_char_length= max_key_length / cs->mbmaxlen;
00397 local_char_length= my_charpos(cs, blob1, blob1+blob_length,
00398 local_char_length);
00399 set_if_smaller(blob_length, local_char_length);
00400 return Field_blob::cmp(blob1, blob_length,
00401 key_ptr+HA_KEY_BLOB_LENGTH,
00402 uint2korr(key_ptr));
00403 }
00404
00405 int Field_blob::key_cmp(const unsigned char *a,const unsigned char *b)
00406 {
00407 return Field_blob::cmp(a+HA_KEY_BLOB_LENGTH, uint2korr(a),
00408 b+HA_KEY_BLOB_LENGTH, uint2korr(b));
00409 }
00410
00411 uint32_t Field_blob::sort_length() const
00412 {
00413 return (uint32_t) (getTable()->getSession()->variables.max_sort_length +
00414 (field_charset == &my_charset_bin ? 0 : sizeof(uint32_t)));
00415 }
00416
00417 void Field_blob::sort_string(unsigned char *to,uint32_t length)
00418 {
00419 unsigned char *blob;
00420 uint32_t blob_length=get_length();
00421
00422 if (!blob_length)
00423 memset(to, 0, length);
00424 else
00425 {
00426 if (field_charset == &my_charset_bin)
00427 {
00428 unsigned char *pos;
00429
00430
00431
00432
00433 length-= sizeof(uint32_t);
00434 pos= to+length;
00435
00436 mi_int4store(pos, blob_length);
00437 }
00438 memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
00439
00440 blob_length= field_charset->strnxfrm(to, length, blob, blob_length);
00441 assert(blob_length == length);
00442 }
00443 }
00444
00445 uint32_t Field_blob::pack_length() const
00446 {
00447 return (uint32_t) (sizeof(uint32_t) + portable_sizeof_char_ptr);
00448 }
00449
00450 unsigned char *Field_blob::pack(unsigned char *to, const unsigned char *from,
00451 uint32_t max_length, bool low_byte_first)
00452 {
00453 unsigned char *save= ptr;
00454 ptr= (unsigned char*) from;
00455 uint32_t length= get_length();
00456
00457
00458
00459
00460
00461
00462 store_length(to, min(length, max_length), low_byte_first);
00463
00464
00465
00466
00467 if (length > 0)
00468 {
00469 from= get_ptr();
00470 memcpy(to+sizeof(uint32_t), from,length);
00471 }
00472
00473 ptr= save;
00474 return(to+sizeof(uint32_t)+length);
00475 }
00476
00494 const unsigned char *Field_blob::unpack(unsigned char *,
00495 const unsigned char *from,
00496 uint32_t,
00497 bool low_byte_first)
00498 {
00499 uint32_t const length= get_length(from, low_byte_first);
00500 getTable()->setWriteSet(position());
00501 store(reinterpret_cast<const char*>(from) + sizeof(uint32_t),
00502 length, field_charset);
00503 return(from + sizeof(uint32_t) + length);
00504 }
00505
00508 unsigned char *
00509 Field_blob::pack_key(unsigned char *to, const unsigned char *from, uint32_t max_length,
00510 bool )
00511 {
00512 unsigned char *save= ptr;
00513 ptr= (unsigned char*) from;
00514 uint32_t length=get_length();
00515 uint32_t local_char_length= ((field_charset->mbmaxlen > 1) ?
00516 max_length/field_charset->mbmaxlen : max_length);
00517 if (length)
00518 from= get_ptr();
00519 if (length > local_char_length)
00520 local_char_length= my_charpos(field_charset, from, from+length,
00521 local_char_length);
00522 set_if_smaller(length, local_char_length);
00523 *to++= (unsigned char) length;
00524 if (max_length > 255)
00525 *to++= (unsigned char) (length >> 8);
00526 memcpy(to, from, length);
00527 ptr=save;
00528 return to+length;
00529 }
00530
00531
00539 uint32_t Field_blob::max_display_length()
00540 {
00541 return (uint32_t) 4294967295U;
00542 }
00543
00544 }