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 * 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, &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= 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   Functions to create a packed row.
00304   Here the number of length bytes are depending on the given max_length
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   /* Length always stored little-endian */
00317   *to++= length & 0xFF;
00318   if (max_length > 255)
00319     *to++= (length >> 8) & 0xFF;
00320 
00321   /* Store bytes of string */
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 /* l_bytes == 2 */
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   /* Key is always stored with 2 bytes */
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       Must clear this as we do a memcmp in optimizer/range.cc to detect
00393       identical keys
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   /* Key is always stored with 2 bytes */
00410   int2store(buff,f_length);
00411   memcpy(buff+HA_KEY_BLOB_LENGTH, pos, f_length);
00412   if (f_length < length)
00413   {
00414     /*
00415       Must clear this as we do a memcmp in optimizer/range.cc to detect
00416       identical keys
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);      // Real length is here
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     /* Keys length prefixes are always packed with 2 bytes */
00476     res->length_bytes= 2;
00477   }
00478   return res;
00479 }
00480 
00481 } /* namespace drizzled */