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