Drizzled Public API Documentation

str.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/str.h>
00024 #include <drizzled/error.h>
00025 #include <drizzled/table.h>
00026 #include <drizzled/session.h>
00027 #include <drizzled/internal/m_string.h>
00028 
00029 namespace drizzled {
00030 
00031 namespace internal
00032 {
00033   extern char _dig_vec_upper[];
00034 }
00035 
00036 Field_str::Field_str(unsigned char *ptr_arg,
00037                      uint32_t len_arg,
00038                      unsigned char *null_ptr_arg,
00039                      unsigned char null_bit_arg,
00040                      const char *field_name_arg,
00041                      const charset_info_st * const charset_arg)
00042   :Field(ptr_arg, len_arg,
00043          null_ptr_arg,
00044          null_bit_arg,
00045          Field::NONE,
00046          field_name_arg)
00047 {
00048   field_charset= charset_arg;
00049   if (charset_arg->state & MY_CS_BINSORT)
00050     flags|= BINARY_FLAG;
00051   field_derivation= DERIVATION_IMPLICIT;
00052 }
00053 
00054 /*
00055   Check if we lost any important data and send a truncation error/warning
00056 
00057   SYNOPSIS
00058     Field_str::report_if_important_data()
00059     ptr                      - Truncated rest of string
00060     end                      - End of truncated string
00061 
00062   RETURN VALUES
00063     0   - None was truncated (or we don't count cut fields)
00064     2   - Some bytes was truncated
00065 
00066   NOTE
00067     Check if we lost any important data (anything in a binary string,
00068     or any non-space in others). If only trailing spaces was lost,
00069     send a truncation note, otherwise send a truncation error.
00070 */
00071 
00072 int Field_str::report_if_important_data(const char *field_ptr, const char *end)
00073 {
00074   if (field_ptr < end && getTable()->in_use->count_cuted_fields)
00075   {
00076     set_warning(DRIZZLE_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
00077     return 2;
00078   }
00079   return 0;
00080 }
00081 
00102 int Field_str::store_decimal(const type::Decimal *d)
00103 {
00104   char buff[DECIMAL_MAX_STR_LENGTH+1];
00105   String str(buff, sizeof(buff), &my_charset_bin);
00106   class_decimal2string(d, 0, &str);
00107   return store(str.ptr(), str.length(), str.charset());
00108 }
00109 
00110 type::Decimal *Field_str::val_decimal(type::Decimal *decimal_value) const
00111 {
00112   int2_class_decimal(E_DEC_FATAL_ERROR, val_int(), 0, decimal_value);
00113   return decimal_value;
00114 }
00115 
00124 int Field_str::store(double nr)
00125 {
00126   char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
00127   uint32_t local_char_length= field_length / charset()->mbmaxlen;
00128   bool error;
00129 
00130   ASSERT_COLUMN_MARKED_FOR_WRITE;
00131 
00132   size_t length= internal::my_gcvt(nr, internal::MY_GCVT_ARG_DOUBLE, local_char_length, buff, &error);
00133   if (error)
00134   {
00135     if (getTable()->getSession()->abortOnWarning())
00136     {
00137       set_warning(DRIZZLE_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
00138     }
00139     else
00140     {
00141       set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
00142     }
00143   }
00144   return store(buff, length, charset());
00145 }
00146 
00147 
00148 bool check_string_copy_error(Field_str *field,
00149                              const char *well_formed_error_pos,
00150                              const char *cannot_convert_error_pos,
00151                              const char *end,
00152                              const charset_info_st * const cs)
00153 {
00154   const char* pos= well_formed_error_pos;
00155   if (not pos && not (pos= cannot_convert_error_pos))
00156     return false;
00157 
00158   const char* end_orig= end;
00159   set_if_smaller(end, pos + 6);
00160 
00161   char tmp[64];
00162   char* t= tmp;
00163   for (; pos < end; pos++)
00164   {
00165     /*
00166       If the source string is ASCII compatible (mbminlen==1)
00167       and the source character is in ASCII printable range (0x20..0x7F),
00168       then display the character as is.
00169 
00170       Otherwise, if the source string is not ASCII compatible (e.g. UCS2),
00171       or the source character is not in the printable range,
00172       then print the character using HEX notation.
00173     */
00174     if (((unsigned char) *pos) >= 0x20 && ((unsigned char) *pos) <= 0x7F && cs->mbminlen == 1)
00175     {
00176       *t++= *pos;
00177     }
00178     else
00179     {
00180       *t++= '\\';
00181       *t++= 'x';
00182       *t++= internal::_dig_vec_upper[((unsigned char) *pos) >> 4];
00183       *t++= internal::_dig_vec_upper[((unsigned char) *pos) & 15];
00184     }
00185   }
00186   if (end_orig > end)
00187   {
00188     *t++= '.';
00189     *t++= '.';
00190     *t++= '.';
00191   }
00192   *t= '\0';
00193   push_warning_printf(field->getTable()->in_use,
00194                       field->getTable()->in_use->abortOnWarning() ? DRIZZLE_ERROR::WARN_LEVEL_ERROR : DRIZZLE_ERROR::WARN_LEVEL_WARN,
00195                       ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
00196                       ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
00197                       "string", tmp, field->field_name,
00198                       (uint32_t) field->getTable()->in_use->row_count);
00199   return true;
00200 }
00201 
00202 uint32_t Field_str::max_data_length() const
00203 {
00204   return field_length + (field_length > 255 ? 2 : 1);
00205 }
00206 
00207 } /* namespace drizzled */