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/varstring.h>
00024 #include <drizzled/table.h>
00025 #include <drizzled/session.h>
00026 #include <plugin/myisam/myisam.h>
00027
00028 #include <string>
00029
00030 using namespace std;
00031
00032 namespace drizzled
00033 {
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 const uint32_t Field_varstring::MAX_SIZE= UINT16_MAX;
00052
00053 Field_varstring::Field_varstring(unsigned char *ptr_arg,
00054 uint32_t len_arg,
00055 uint32_t length_bytes_arg,
00056 unsigned char *null_ptr_arg,
00057 unsigned char null_bit_arg,
00058 const char *field_name_arg,
00059 const CHARSET_INFO * const cs) :
00060 Field_str(ptr_arg,
00061 len_arg,
00062 null_ptr_arg,
00063 null_bit_arg,
00064 field_name_arg, cs),
00065 length_bytes(length_bytes_arg)
00066 {
00067 }
00068
00069 Field_varstring::Field_varstring(uint32_t len_arg,
00070 bool maybe_null_arg,
00071 const char *field_name_arg,
00072 const CHARSET_INFO * const cs) :
00073 Field_str((unsigned char*) 0,
00074 len_arg,
00075 maybe_null_arg ? (unsigned char*) "": 0,
00076 0,
00077 field_name_arg,
00078 cs),
00079 length_bytes(len_arg < 256 ? 1 :2)
00080 {
00081 }
00082
00083 int Field_varstring::store(const char *from,uint32_t length, const CHARSET_INFO * const cs)
00084 {
00085 uint32_t copy_length;
00086 const char *well_formed_error_pos;
00087 const char *cannot_convert_error_pos;
00088 const char *from_end_pos;
00089
00090 ASSERT_COLUMN_MARKED_FOR_WRITE;
00091
00092 copy_length= well_formed_copy_nchars(field_charset,
00093 (char*) ptr + length_bytes,
00094 field_length,
00095 cs, from, length,
00096 field_length / field_charset->mbmaxlen,
00097 &well_formed_error_pos,
00098 &cannot_convert_error_pos,
00099 &from_end_pos);
00100
00101 if (length_bytes == 1)
00102 *ptr= (unsigned char) copy_length;
00103 else
00104 int2store(ptr, copy_length);
00105
00106 if (check_string_copy_error(this, well_formed_error_pos,
00107 cannot_convert_error_pos, from + length, cs))
00108 return 2;
00109
00110 return report_if_important_data(from_end_pos, from + length);
00111 }
00112
00113
00114 int Field_varstring::store(int64_t nr, bool unsigned_val)
00115 {
00116 char buff[64];
00117 uint32_t length;
00118 length= (uint32_t) (field_charset->cset->int64_t10_to_str)(field_charset,
00119 buff,
00120 sizeof(buff),
00121 (unsigned_val ? 10: -10),
00122 nr);
00123 return Field_varstring::store(buff, length, field_charset);
00124 }
00125
00126
00127 double Field_varstring::val_real(void) const
00128 {
00129 int not_used;
00130 char *end_not_used;
00131
00132 ASSERT_COLUMN_MARKED_FOR_READ;
00133
00134 uint32_t length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
00135
00136 return my_strntod(field_charset, (char*) ptr+length_bytes, length,
00137 &end_not_used, ¬_used);
00138 }
00139
00140
00141 int64_t Field_varstring::val_int(void) const
00142 {
00143 int not_used;
00144 char *end_not_used;
00145 uint32_t length;
00146
00147 ASSERT_COLUMN_MARKED_FOR_READ;
00148
00149 length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
00150
00151 return my_strntoll(field_charset, (char*) ptr+length_bytes, length, 10,
00152 &end_not_used, ¬_used);
00153 }
00154
00155 String *Field_varstring::val_str(String *, String *val_ptr) const
00156 {
00157 uint32_t length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
00158
00159 ASSERT_COLUMN_MARKED_FOR_READ;
00160
00161 val_ptr->set((const char*) ptr+length_bytes, length, field_charset);
00162
00163 return val_ptr;
00164 }
00165
00166
00167 type::Decimal *Field_varstring::val_decimal(type::Decimal *decimal_value) const
00168 {
00169 uint32_t length;
00170
00171 ASSERT_COLUMN_MARKED_FOR_READ;
00172
00173 length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
00174
00175 decimal_value->store(E_DEC_FATAL_ERROR, (char*) ptr+length_bytes, length, charset());
00176
00177 return decimal_value;
00178 }
00179
00180
00181 int Field_varstring::cmp_max(const unsigned char *a_ptr, const unsigned char *b_ptr,
00182 uint32_t max_len)
00183 {
00184 uint32_t a_length, b_length;
00185 int diff;
00186
00187 if (length_bytes == 1)
00188 {
00189 a_length= (uint32_t) *a_ptr;
00190 b_length= (uint32_t) *b_ptr;
00191 }
00192 else
00193 {
00194 a_length= uint2korr(a_ptr);
00195 b_length= uint2korr(b_ptr);
00196 }
00197 set_if_smaller(a_length, max_len);
00198 set_if_smaller(b_length, max_len);
00199 diff= field_charset->coll->strnncollsp(field_charset,
00200 a_ptr+
00201 length_bytes,
00202 a_length,
00203 b_ptr+
00204 length_bytes,
00205 b_length,0);
00206 return diff;
00207 }
00208
00209
00215 int Field_varstring::key_cmp(const unsigned char *key_ptr, uint32_t max_key_length)
00216 {
00217 uint32_t length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
00218 uint32_t local_char_length= max_key_length / field_charset->mbmaxlen;
00219
00220 local_char_length= my_charpos(field_charset, ptr + length_bytes,
00221 ptr + length_bytes + length, local_char_length);
00222 set_if_smaller(length, local_char_length);
00223 return field_charset->coll->strnncollsp(field_charset,
00224 ptr + length_bytes,
00225 length,
00226 key_ptr+
00227 HA_KEY_BLOB_LENGTH,
00228 uint2korr(key_ptr), 0);
00229 }
00230
00231
00240 int Field_varstring::key_cmp(const unsigned char *a,const unsigned char *b)
00241 {
00242 return field_charset->coll->strnncollsp(field_charset,
00243 a + HA_KEY_BLOB_LENGTH,
00244 uint2korr(a),
00245 b + HA_KEY_BLOB_LENGTH,
00246 uint2korr(b),
00247 0);
00248 }
00249
00250
00251 void Field_varstring::sort_string(unsigned char *to,uint32_t length)
00252 {
00253 uint32_t tot_length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
00254
00255 if (field_charset == &my_charset_bin)
00256 {
00257
00258 if (length_bytes == 1)
00259 to[length-1]= tot_length;
00260 else
00261 mi_int2store(to+length-2, tot_length);
00262 length-= length_bytes;
00263 }
00264
00265 tot_length= my_strnxfrm(field_charset,
00266 to, length, ptr + length_bytes,
00267 tot_length);
00268 assert(tot_length == length);
00269 }
00270
00271
00272 enum ha_base_keytype Field_varstring::key_type() const
00273 {
00274 enum ha_base_keytype res;
00275
00276 if (binary())
00277 res= length_bytes == 1 ? HA_KEYTYPE_VARBINARY1 : HA_KEYTYPE_VARBINARY2;
00278 else
00279 res= length_bytes == 1 ? HA_KEYTYPE_VARTEXT1 : HA_KEYTYPE_VARTEXT2;
00280 return res;
00281 }
00282
00283
00284 void Field_varstring::sql_type(String &res) const
00285 {
00286 const CHARSET_INFO * const cs=res.charset();
00287 uint32_t length;
00288
00289 length= cs->cset->snprintf(cs,(char*) res.ptr(),
00290 res.alloced_length(), "%s(%d)",
00291 (has_charset() ? "varchar" : "varbinary"),
00292 (int) field_length / charset()->mbmaxlen);
00293 res.length(length);
00294 }
00295
00296
00297 uint32_t Field_varstring::used_length()
00298 {
00299 return length_bytes == 1 ? 1 + (uint32_t) (unsigned char) *ptr : 2 + uint2korr(ptr);
00300 }
00301
00302
00303
00304
00305
00306
00307 unsigned char *Field_varstring::pack(unsigned char *to, const unsigned char *from,
00308 uint32_t max_length,
00309 bool )
00310 {
00311 uint32_t length= length_bytes == 1 ? (uint32_t) *from : uint2korr(from);
00312 set_if_smaller(max_length, field_length);
00313 if (length > max_length)
00314 length=max_length;
00315
00316
00317 *to++= length & 0xFF;
00318 if (max_length > 255)
00319 *to++= (length >> 8) & 0xFF;
00320
00321
00322 if (length > 0)
00323 memcpy(to, from+length_bytes, length);
00324 return to+length;
00325 }
00326
00327
00343 const unsigned char *
00344 Field_varstring::unpack(unsigned char *to, const unsigned char *from,
00345 uint32_t param_data,
00346 bool )
00347 {
00348 uint32_t length;
00349 uint32_t l_bytes= (param_data && (param_data < field_length)) ?
00350 (param_data <= 255) ? 1 : 2 : length_bytes;
00351 if (l_bytes == 1)
00352 {
00353 to[0]= *from++;
00354 length= to[0];
00355 if (length_bytes == 2)
00356 to[1]= 0;
00357 }
00358 else
00359 {
00360 length= uint2korr(from);
00361 to[0]= *from++;
00362 to[1]= *from++;
00363 }
00364 if (length)
00365 memcpy(to+ length_bytes, from, length);
00366 return from+length;
00367 }
00368
00369
00370 uint32_t Field_varstring::max_packed_col_length(uint32_t max_length)
00371 {
00372 return (max_length > 255 ? 2 : 1)+max_length;
00373 }
00374
00375 uint32_t Field_varstring::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
00376 {
00377
00378 const uint32_t key_len= 2;
00379 uint32_t f_length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
00380 uint32_t local_char_length= length / field_charset->mbmaxlen;
00381 unsigned char *pos= ptr+length_bytes;
00382 local_char_length= my_charpos(field_charset, pos, pos + f_length,
00383 local_char_length);
00384 set_if_smaller(f_length, local_char_length);
00385 unsigned char len_buff[key_len];
00386 int2store(len_buff,f_length);
00387 buff.append(len_buff);
00388 buff.append(pos, f_length);
00389 if (f_length < length)
00390 {
00391
00392
00393
00394
00395 buff.append(length-f_length, 0);
00396 }
00397 return key_len+f_length;
00398 }
00399
00400
00401 uint32_t Field_varstring::get_key_image(unsigned char *buff, uint32_t length)
00402 {
00403 uint32_t f_length= length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
00404 uint32_t local_char_length= length / field_charset->mbmaxlen;
00405 unsigned char *pos= ptr+length_bytes;
00406 local_char_length= my_charpos(field_charset, pos, pos + f_length,
00407 local_char_length);
00408 set_if_smaller(f_length, local_char_length);
00409
00410 int2store(buff,f_length);
00411 memcpy(buff+HA_KEY_BLOB_LENGTH, pos, f_length);
00412 if (f_length < length)
00413 {
00414
00415
00416
00417
00418 memset(buff+HA_KEY_BLOB_LENGTH+f_length, 0, (length-f_length));
00419 }
00420 return HA_KEY_BLOB_LENGTH+f_length;
00421 }
00422
00423 void Field_varstring::set_key_image(const unsigned char *buff, uint32_t length)
00424 {
00425 length= uint2korr(buff);
00426 (void) Field_varstring::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
00427 }
00428
00429 int Field_varstring::cmp_binary(const unsigned char *a_ptr,
00430 const unsigned char *b_ptr,
00431 uint32_t max_length)
00432 {
00433 uint32_t a_length,b_length;
00434
00435 if (length_bytes == 1)
00436 {
00437 a_length= (uint32_t) *a_ptr;
00438 b_length= (uint32_t) *b_ptr;
00439 }
00440 else
00441 {
00442 a_length= uint2korr(a_ptr);
00443 b_length= uint2korr(b_ptr);
00444 }
00445 set_if_smaller(a_length, max_length);
00446 set_if_smaller(b_length, max_length);
00447 if (a_length != b_length)
00448 return 1;
00449 return memcmp(a_ptr+length_bytes, b_ptr+length_bytes, a_length);
00450 }
00451
00452
00453 Field *Field_varstring::new_field(memory::Root *root, Table *new_table, bool keep_type)
00454 {
00455 Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table,
00456 keep_type);
00457 if (res)
00458 res->length_bytes= length_bytes;
00459 return res;
00460 }
00461
00462
00463 Field *Field_varstring::new_key_field(memory::Root *root,
00464 Table *new_table,
00465 unsigned char *new_ptr, unsigned char *new_null_ptr,
00466 uint32_t new_null_bit)
00467 {
00468 Field_varstring *res;
00469 if ((res= (Field_varstring*) Field::new_key_field(root,
00470 new_table,
00471 new_ptr,
00472 new_null_ptr,
00473 new_null_bit)))
00474 {
00475
00476 res->length_bytes= 2;
00477 }
00478 return res;
00479 }
00480
00481 }