~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/str.cc

Merged in latest plugin-slot-reorg.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* - mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008 MySQL
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
 
20
 
 
21
 
 
22
#include <drizzled/server_includes.h>
 
23
#include <drizzled/field/str.h>
 
24
#include <drizzled/error.h>
 
25
#include <drizzled/table.h>
 
26
#include <drizzled/session.h>
 
27
 
 
28
 
 
29
Field_str::Field_str(unsigned char *ptr_arg,uint32_t len_arg,
 
30
                     unsigned char *null_ptr_arg,
 
31
                     unsigned char null_bit_arg, utype unireg_check_arg,
 
32
                     const char *field_name_arg,
 
33
                     const CHARSET_INFO * const charset_arg)
 
34
  :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
 
35
         unireg_check_arg, field_name_arg)
 
36
{
 
37
  field_charset= charset_arg;
 
38
  if (charset_arg->state & MY_CS_BINSORT)
 
39
    flags|=BINARY_FLAG;
 
40
  field_derivation= DERIVATION_IMPLICIT;
 
41
}
 
42
 
 
43
/*
 
44
  Check if we lost any important data and send a truncation error/warning
 
45
 
 
46
  SYNOPSIS
 
47
    Field_str::report_if_important_data()
 
48
    ptr                      - Truncated rest of string
 
49
    end                      - End of truncated string
 
50
 
 
51
  RETURN VALUES
 
52
    0   - None was truncated (or we don't count cut fields)
 
53
    2   - Some bytes was truncated
 
54
 
 
55
  NOTE
 
56
    Check if we lost any important data (anything in a binary string,
 
57
    or any non-space in others). If only trailing spaces was lost,
 
58
    send a truncation note, otherwise send a truncation error.
 
59
*/
 
60
 
 
61
int
 
62
Field_str::report_if_important_data(const char *field_ptr, const char *end)
 
63
{
 
64
  if ((field_ptr < end) && table->in_use->count_cuted_fields)
 
65
  {
 
66
    if (test_if_important_data(field_charset, field_ptr, end))
 
67
    {
 
68
      if (table->in_use->abort_on_warning)
 
69
        set_warning(DRIZZLE_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
 
70
      else
 
71
        set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
72
    }
 
73
    else /* If we lost only spaces then produce a NOTE, not a WARNING */
 
74
      set_warning(DRIZZLE_ERROR::WARN_LEVEL_NOTE, ER_WARN_DATA_TRUNCATED, 1);
 
75
    return 2;
 
76
  }
 
77
  return 0;
 
78
}
 
79
 
 
80
/**
 
81
  Decimal representation of Field_str.
 
82
 
 
83
  @param d         value for storing
 
84
 
 
85
  @note
 
86
    Field_str is the base class for fields like Field_enum,
 
87
    Field_date and some similar. Some dates use fraction and also
 
88
    string value should be converted to floating point value according
 
89
    our rules, so we use double to store value of decimal in string.
 
90
 
 
91
  @todo
 
92
    use decimal2string?
 
93
 
 
94
  @retval
 
95
    0     OK
 
96
  @retval
 
97
    !=0  error
 
98
*/
 
99
 
 
100
int Field_str::store_decimal(const my_decimal *d)
 
101
{
 
102
  char buff[DECIMAL_MAX_STR_LENGTH+1];
 
103
  String str(buff, sizeof(buff), &my_charset_bin);
 
104
  my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
 
105
  return store(str.ptr(), str.length(), str.charset());
 
106
}
 
107
 
 
108
my_decimal *Field_str::val_decimal(my_decimal *decimal_value)
 
109
{
 
110
  int64_t nr= val_int();
 
111
  int2my_decimal(E_DEC_FATAL_ERROR, nr, 0, decimal_value);
 
112
  return decimal_value;
 
113
}
 
114
 
 
115
/**
 
116
  Store double value in Field_varstring.
 
117
 
 
118
  Pretty prints double number into field_length characters buffer.
 
119
 
 
120
  @param nr            number
 
121
*/
 
122
 
 
123
int Field_str::store(double nr)
 
124
{
 
125
  char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
 
126
  uint32_t local_char_length= field_length / charset()->mbmaxlen;
 
127
  size_t length;
 
128
  bool error;
 
129
 
 
130
  ASSERT_COLUMN_MARKED_FOR_WRITE;
 
131
 
 
132
  length= my_gcvt(nr, MY_GCVT_ARG_DOUBLE, local_char_length, buff, &error);
 
133
  if (error)
 
134
  {
 
135
    if (table->in_use->abort_on_warning)
 
136
      set_warning(DRIZZLE_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1);
 
137
    else
 
138
      set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
139
  }
 
140
  return store(buff, length, charset());
 
141
}
 
142
 
 
143
/* If one of the fields is binary and the other one isn't return 1 else 0 */
 
144
 
 
145
bool Field_str::compare_str_field_flags(CreateField *new_field_ptr,
 
146
                                        uint32_t flag_arg)
 
147
{
 
148
  return (((new_field_ptr->flags & (BINCMP_FLAG | BINARY_FLAG)) &&
 
149
          !(flag_arg & (BINCMP_FLAG | BINARY_FLAG))) ||
 
150
         (!(new_field_ptr->flags & (BINCMP_FLAG | BINARY_FLAG)) &&
 
151
          (flag_arg & (BINCMP_FLAG | BINARY_FLAG))));
 
152
}
 
153
 
 
154
 
 
155
uint32_t Field_str::is_equal(CreateField *new_field_ptr)
 
156
{
 
157
  if (compare_str_field_flags(new_field_ptr, flags))
 
158
    return 0;
 
159
 
 
160
  return ((new_field_ptr->sql_type == real_type()) &&
 
161
          new_field_ptr->charset == field_charset &&
 
162
          new_field_ptr->length == max_display_length());
 
163
}
 
164
 
 
165
 
 
166
bool check_string_copy_error(Field_str *field,
 
167
                             const char *well_formed_error_pos,
 
168
                             const char *cannot_convert_error_pos,
 
169
                             const char *end,
 
170
                             const CHARSET_INFO * const cs)
 
171
{
 
172
  const char *pos, *end_orig;
 
173
  char tmp[64], *t;
 
174
 
 
175
  if (!(pos= well_formed_error_pos) &&
 
176
      !(pos= cannot_convert_error_pos))
 
177
    return false;
 
178
 
 
179
  end_orig= end;
 
180
  set_if_smaller(end, pos + 6);
 
181
 
 
182
  for (t= tmp; pos < end; pos++)
 
183
  {
 
184
    /*
 
185
      If the source string is ASCII compatible (mbminlen==1)
 
186
      and the source character is in ASCII printable range (0x20..0x7F),
 
187
      then display the character as is.
 
188
 
 
189
      Otherwise, if the source string is not ASCII compatible (e.g. UCS2),
 
190
      or the source character is not in the printable range,
 
191
      then print the character using HEX notation.
 
192
    */
 
193
    if (((unsigned char) *pos) >= 0x20 &&
 
194
        ((unsigned char) *pos) <= 0x7F &&
 
195
        cs->mbminlen == 1)
 
196
    {
 
197
      *t++= *pos;
 
198
    }
 
199
    else
 
200
    {
 
201
      *t++= '\\';
 
202
      *t++= 'x';
 
203
      *t++= _dig_vec_upper[((unsigned char) *pos) >> 4];
 
204
      *t++= _dig_vec_upper[((unsigned char) *pos) & 15];
 
205
    }
 
206
  }
 
207
  if (end_orig > end)
 
208
  {
 
209
    *t++= '.';
 
210
    *t++= '.';
 
211
    *t++= '.';
 
212
  }
 
213
  *t= '\0';
 
214
  push_warning_printf(field->table->in_use,
 
215
                      field->table->in_use->abort_on_warning ?
 
216
                      DRIZZLE_ERROR::WARN_LEVEL_ERROR :
 
217
                      DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
218
                      ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
 
219
                      ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
 
220
                      "string", tmp, field->field_name,
 
221
                      (uint32_t) field->table->in_use->row_count);
 
222
  return true;
 
223
}
 
224
 
 
225
uint32_t Field_str::max_data_length() const
 
226
{
 
227
  return field_length + (field_length > 255 ? 2 : 1);
 
228
}
 
229