Drizzled Public API Documentation

varstring.cc
00001 /* - mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 MySQL
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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   VARCHAR type
00037   Data in field->ptr is stored as:
00038     1 or 2 bytes length-prefix-header  (from Field_varstring::length_bytes)
00039     data
00040 
00041   NOTE:
00042   When VARCHAR is stored in a key (for handler::index_read() etc) it's always
00043   stored with a 2 byte prefix. (Just like blob keys).
00044 
00045   Normally length_bytes is calculated as (field_length < 256 : 1 ? 2)
00046   The exception is if there is a prefix key field that is part of a long
00047   VARCHAR, in which case field_length for this may be 1 but the length_bytes
00048   is 2.
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_st * 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_st * 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_st * 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, &not_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, &not_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     /* Store length last in high-byte order to sort longer strings first */
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= field_charset->strnxfrm(to, length, ptr + length_bytes, tot_length);
00266   assert(tot_length == length);
00267 }
00268 
00269 
00270 enum ha_base_keytype Field_varstring::key_type() const
00271 {
00272   enum ha_base_keytype res;
00273 
00274   if (binary())
00275     res= length_bytes == 1 ? HA_KEYTYPE_VARBINARY1 : HA_KEYTYPE_VARBINARY2;
00276   else
00277     res= length_bytes == 1 ? HA_KEYTYPE_VARTEXT1 : HA_KEYTYPE_VARTEXT2;
00278   return res;
00279 }
00280 
00281 
00282 uint32_t Field_varstring::used_length()
00283 {
00284   return length_bytes == 1 ? 1 + (uint32_t) (unsigned char) *ptr : 2 + uint2korr(ptr);
00285 }
00286 
00287 /*
00288   Functions to create a packed row.
00289   Here the number of length bytes are depending on the given max_length
00290 */
00291 
00292 unsigned char *Field_varstring::pack(unsigned char *to, const unsigned char *from,
00293                              uint32_t max_length,
00294                              bool )
00295 {
00296   uint32_t length= length_bytes == 1 ? (uint32_t) *from : uint2korr(from);
00297   set_if_smaller(max_length, field_length);
00298   if (length > max_length)
00299     length=max_length;
00300 
00301   /* Length always stored little-endian */
00302   *to++= length & 0xFF;
00303   if (max_length > 255)
00304     *to++= (length >> 8) & 0xFF;
00305 
00306   /* Store bytes of string */
00307   if (length > 0)
00308     memcpy(to, from+length_bytes, length);
00309   return to+length;
00310 }
00311 
00312 
00328 const unsigned char *
00329 Field_varstring::unpack(unsigned char *to, const unsigned char *from,
00330                         uint32_t param_data,
00331                         bool )
00332 {
00333   uint32_t length;
00334   uint32_t l_bytes= (param_data && (param_data < field_length)) ?
00335                 (param_data <= 255) ? 1 : 2 : length_bytes;
00336   if (l_bytes == 1)
00337   {
00338     to[0]= *from++;
00339     length= to[0];
00340     if (length_bytes == 2)
00341       to[1]= 0;
00342   }
00343   else /* l_bytes == 2 */
00344   {
00345     length= uint2korr(from);
00346     to[0]= *from++;
00347     to[1]= *from++;
00348   }
00349   if (length)
00350     memcpy(to+ length_bytes, from, length);
00351   return from+length;
00352 }
00353 
00354 
00355 uint32_t Field_varstring::max_packed_col_length(uint32_t max_length)
00356 {
00357   return (max_length > 255 ? 2 : 1)+max_length;
00358 }
00359 
00360 uint32_t Field_varstring::get_key_image(basic_string<unsigned char> &buff, uint32_t length)
00361 {
00362   /* Key is always stored with 2 bytes */
00363   const uint32_t key_len= 2;
00364   uint32_t f_length=  length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
00365   uint32_t local_char_length= length / field_charset->mbmaxlen;
00366   unsigned char *pos= ptr+length_bytes;
00367   local_char_length= my_charpos(field_charset, pos, pos + f_length,
00368                                 local_char_length);
00369   set_if_smaller(f_length, local_char_length);
00370   unsigned char len_buff[key_len];
00371   int2store(len_buff,f_length);
00372   buff.append(len_buff);
00373   buff.append(pos, f_length);
00374   if (f_length < length)
00375   {
00376     /*
00377       Must clear this as we do a memcmp in optimizer/range.cc to detect
00378       identical keys
00379     */
00380     buff.append(length-f_length, 0);
00381   }
00382   return key_len+f_length;
00383 }
00384 
00385 
00386 uint32_t Field_varstring::get_key_image(unsigned char *buff, uint32_t length)
00387 {
00388   uint32_t f_length=  length_bytes == 1 ? (uint32_t) *ptr : uint2korr(ptr);
00389   uint32_t local_char_length= length / field_charset->mbmaxlen;
00390   unsigned char *pos= ptr+length_bytes;
00391   local_char_length= my_charpos(field_charset, pos, pos + f_length,
00392                                 local_char_length);
00393   set_if_smaller(f_length, local_char_length);
00394   /* Key is always stored with 2 bytes */
00395   int2store(buff,f_length);
00396   memcpy(buff+HA_KEY_BLOB_LENGTH, pos, f_length);
00397   if (f_length < length)
00398   {
00399     /*
00400       Must clear this as we do a memcmp in optimizer/range.cc to detect
00401       identical keys
00402     */
00403     memset(buff+HA_KEY_BLOB_LENGTH+f_length, 0, (length-f_length));
00404   }
00405   return HA_KEY_BLOB_LENGTH+f_length;
00406 }
00407 
00408 void Field_varstring::set_key_image(const unsigned char *buff, uint32_t length)
00409 {
00410   length= uint2korr(buff);      // Real length is here
00411   (void) Field_varstring::store((const char*) buff+HA_KEY_BLOB_LENGTH, length, field_charset);
00412 }
00413 
00414 int Field_varstring::cmp_binary(const unsigned char *a_ptr,
00415                                 const unsigned char *b_ptr,
00416                                 uint32_t max_length)
00417 {
00418   uint32_t a_length,b_length;
00419 
00420   if (length_bytes == 1)
00421   {
00422     a_length= (uint32_t) *a_ptr;
00423     b_length= (uint32_t) *b_ptr;
00424   }
00425   else
00426   {
00427     a_length= uint2korr(a_ptr);
00428     b_length= uint2korr(b_ptr);
00429   }
00430   set_if_smaller(a_length, max_length);
00431   set_if_smaller(b_length, max_length);
00432   if (a_length != b_length)
00433     return 1;
00434   return memcmp(a_ptr+length_bytes, b_ptr+length_bytes, a_length);
00435 }
00436 
00437 
00438 Field *Field_varstring::new_field(memory::Root *root, Table *new_table, bool keep_type)
00439 {
00440   Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table,
00441                                                             keep_type);
00442   if (res)
00443     res->length_bytes= length_bytes;
00444   return res;
00445 }
00446 
00447 
00448 Field *Field_varstring::new_key_field(memory::Root *root,
00449                                       Table *new_table,
00450                                       unsigned char *new_ptr, unsigned char *new_null_ptr,
00451                                       uint32_t new_null_bit)
00452 {
00453   Field_varstring *res;
00454   if ((res= (Field_varstring*) Field::new_key_field(root,
00455                                                     new_table,
00456                                                     new_ptr,
00457                                                     new_null_ptr,
00458                                                     new_null_bit)))
00459   {
00460     /* Keys length prefixes are always packed with 2 bytes */
00461     res->length_bytes= 2;
00462   }
00463   return res;
00464 }
00465 
00466 } /* namespace drizzled */