~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/enum.cc

  • Committer: Monty Taylor
  • Date: 2008-08-04 19:37:18 UTC
  • mto: (261.2.2 codestyle)
  • mto: This revision was merged to the branch mainline in revision 262.
  • Revision ID: monty@inaugust.com-20080804193718-f0rz13uli4429ozb
Changed gettext_noop() to N_()

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/enum.h>
24
 
#include <drizzled/error.h>
25
 
#include <drizzled/table.h>
26
 
#include <drizzled/session.h>
27
 
 
28
 
/****************************************************************************
29
 
** enum type.
30
 
** This is a string which only can have a selection of different values.
31
 
** If one uses this string in a number context one gets the type number.
32
 
****************************************************************************/
33
 
 
34
 
enum ha_base_keytype Field_enum::key_type() const
35
 
{
36
 
  switch (packlength) {
37
 
  default: return HA_KEYTYPE_BINARY;
38
 
  case 2: assert(1);
39
 
  case 3: assert(1);
40
 
  case 4: return HA_KEYTYPE_ULONG_INT;
41
 
  case 8: return HA_KEYTYPE_ULONGLONG;
42
 
  }
43
 
}
44
 
 
45
 
void Field_enum::store_type(uint64_t value)
46
 
{
47
 
  switch (packlength) {
48
 
  case 1: ptr[0]= (unsigned char) value;  break;
49
 
  case 2:
50
 
#ifdef WORDS_BIGENDIAN
51
 
  if (table->s->db_low_byte_first)
52
 
  {
53
 
    int2store(ptr,(unsigned short) value);
54
 
  }
55
 
  else
56
 
#endif
57
 
    shortstore(ptr,(unsigned short) value);
58
 
  break;
59
 
  case 3: int3store(ptr,(long) value); break;
60
 
  case 4:
61
 
#ifdef WORDS_BIGENDIAN
62
 
  if (table->s->db_low_byte_first)
63
 
  {
64
 
    int4store(ptr,value);
65
 
  }
66
 
  else
67
 
#endif
68
 
    longstore(ptr,(long) value);
69
 
  break;
70
 
  case 8:
71
 
#ifdef WORDS_BIGENDIAN
72
 
  if (table->s->db_low_byte_first)
73
 
  {
74
 
    int8store(ptr,value);
75
 
  }
76
 
  else
77
 
#endif
78
 
    int64_tstore(ptr,value); break;
79
 
  }
80
 
}
81
 
 
82
 
 
83
 
/**
84
 
  @note
85
 
    Storing a empty string in a enum field gives a warning
86
 
    (if there isn't a empty value in the enum)
87
 
*/
88
 
 
89
 
int Field_enum::store(const char *from, uint32_t length, const CHARSET_INFO * const cs)
90
 
{
91
 
  int err= 0;
92
 
  uint32_t not_used;
93
 
  char buff[STRING_BUFFER_USUAL_SIZE];
94
 
  String tmpstr(buff,sizeof(buff), &my_charset_bin);
95
 
 
96
 
  /* Convert character set if necessary */
97
 
  if (String::needs_conversion(length, cs, field_charset, &not_used))
98
 
  { 
99
 
    uint32_t dummy_errors;
100
 
    tmpstr.copy(from, length, cs, field_charset, &dummy_errors);
101
 
    from= tmpstr.ptr();
102
 
    length=  tmpstr.length();
103
 
  }
104
 
 
105
 
  /* Remove end space */
106
 
  length= field_charset->cset->lengthsp(field_charset, from, length);
107
 
  uint32_t tmp=find_type2(typelib, from, length, field_charset);
108
 
  if (!tmp)
109
 
  {
110
 
    if (length < 6) // Can't be more than 99999 enums
111
 
    {
112
 
      /* This is for reading numbers with LOAD DATA INFILE */
113
 
      char *end;
114
 
      tmp=(uint) my_strntoul(cs,from,length,10,&end,&err);
115
 
      if (err || end != from+length || tmp > typelib->count)
116
 
      {
117
 
        tmp=0;
118
 
        set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
119
 
      }
120
 
      if (!table->in_use->count_cuted_fields)
121
 
        err= 0;
122
 
    }
123
 
    else
124
 
      set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
125
 
  }
126
 
  store_type((uint64_t) tmp);
127
 
  return err;
128
 
}
129
 
 
130
 
 
131
 
int Field_enum::store(double nr)
132
 
{
133
 
  return Field_enum::store((int64_t) nr, false);
134
 
}
135
 
 
136
 
 
137
 
int Field_enum::store(int64_t nr,
138
 
                      bool unsigned_val __attribute__((unused)))
139
 
{
140
 
  int error= 0;
141
 
  if ((uint64_t) nr > typelib->count || nr == 0)
142
 
  {
143
 
    set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
144
 
    if (nr != 0 || table->in_use->count_cuted_fields)
145
 
    {
146
 
      nr= 0;
147
 
      error= 1;
148
 
    }
149
 
  }
150
 
  store_type((uint64_t) (uint) nr);
151
 
  return error;
152
 
}
153
 
 
154
 
 
155
 
double Field_enum::val_real(void)
156
 
{
157
 
  return (double) Field_enum::val_int();
158
 
}
159
 
 
160
 
 
161
 
int64_t Field_enum::val_int(void)
162
 
{
163
 
  switch (packlength) {
164
 
  case 1:
165
 
    return (int64_t) ptr[0];
166
 
  case 2:
167
 
  {
168
 
    uint16_t tmp;
169
 
#ifdef WORDS_BIGENDIAN
170
 
    if (table->s->db_low_byte_first)
171
 
      tmp=sint2korr(ptr);
172
 
    else
173
 
#endif
174
 
      shortget(tmp,ptr);
175
 
    return (int64_t) tmp;
176
 
  }
177
 
  case 3:
178
 
    return (int64_t) uint3korr(ptr);
179
 
  case 4:
180
 
  {
181
 
    uint32_t tmp;
182
 
#ifdef WORDS_BIGENDIAN
183
 
    if (table->s->db_low_byte_first)
184
 
      tmp=uint4korr(ptr);
185
 
    else
186
 
#endif
187
 
      longget(tmp,ptr);
188
 
    return (int64_t) tmp;
189
 
  }
190
 
  case 8:
191
 
  {
192
 
    int64_t tmp;
193
 
#ifdef WORDS_BIGENDIAN
194
 
    if (table->s->db_low_byte_first)
195
 
      tmp=sint8korr(ptr);
196
 
    else
197
 
#endif
198
 
      int64_tget(tmp,ptr);
199
 
    return tmp;
200
 
  }
201
 
  }
202
 
  return 0;                                     // impossible
203
 
}
204
 
 
205
 
 
206
 
/**
207
 
   Save the field metadata for enum fields.
208
 
 
209
 
   Saves the real type in the first byte and the pack length in the 
210
 
   second byte of the field metadata array at index of *metadata_ptr and
211
 
   *(metadata_ptr + 1).
212
 
 
213
 
   @param   metadata_ptr   First byte of field metadata
214
 
 
215
 
   @returns number of bytes written to metadata_ptr
216
 
*/
217
 
int Field_enum::do_save_field_metadata(unsigned char *metadata_ptr)
218
 
{
219
 
  *metadata_ptr= real_type();
220
 
  *(metadata_ptr + 1)= pack_length();
221
 
  return 2;
222
 
}
223
 
 
224
 
 
225
 
String *Field_enum::val_str(String *val_buffer __attribute__((unused)),
226
 
                            String *val_ptr)
227
 
{
228
 
  uint32_t tmp=(uint) Field_enum::val_int();
229
 
  if (!tmp || tmp > typelib->count)
230
 
    val_ptr->set("", 0, field_charset);
231
 
  else
232
 
    val_ptr->set((const char*) typelib->type_names[tmp-1],
233
 
                 typelib->type_lengths[tmp-1],
234
 
                 field_charset);
235
 
  return val_ptr;
236
 
}
237
 
 
238
 
int Field_enum::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
239
 
{
240
 
  unsigned char *old= ptr;
241
 
  ptr= (unsigned char*) a_ptr;
242
 
  uint64_t a=Field_enum::val_int();
243
 
  ptr= (unsigned char*) b_ptr;
244
 
  uint64_t b=Field_enum::val_int();
245
 
  ptr= old;
246
 
  return (a < b) ? -1 : (a > b) ? 1 : 0;
247
 
}
248
 
 
249
 
void Field_enum::sort_string(unsigned char *to,uint32_t length __attribute__((unused)))
250
 
{
251
 
  uint64_t value=Field_enum::val_int();
252
 
  to+=packlength-1;
253
 
  for (uint32_t i=0 ; i < packlength ; i++)
254
 
  {
255
 
    *to-- = (unsigned char) (value & 255);
256
 
    value>>=8;
257
 
  }
258
 
}
259
 
 
260
 
 
261
 
void Field_enum::sql_type(String &res) const
262
 
{
263
 
  char buffer[255];
264
 
  String enum_item(buffer, sizeof(buffer), res.charset());
265
 
 
266
 
  res.length(0);
267
 
  res.append(STRING_WITH_LEN("enum("));
268
 
 
269
 
  bool flag=0;
270
 
  uint32_t *len= typelib->type_lengths;
271
 
  for (const char **pos= typelib->type_names; *pos; pos++, len++)
272
 
  {
273
 
    uint32_t dummy_errors;
274
 
    if (flag)
275
 
      res.append(',');
276
 
    /* convert to res.charset() == utf8, then quote */
277
 
    enum_item.copy(*pos, *len, charset(), res.charset(), &dummy_errors);
278
 
    append_unescaped(&res, enum_item.ptr(), enum_item.length());
279
 
    flag= 1;
280
 
  }
281
 
  res.append(')');
282
 
}
283
 
 
284
 
 
285
 
Field *Field_enum::new_field(MEM_ROOT *root, Table *new_table,
286
 
                             bool keep_type)
287
 
{
288
 
  Field_enum *res= (Field_enum*) Field::new_field(root, new_table, keep_type);
289
 
  if (res)
290
 
    res->typelib= copy_typelib(root, typelib);
291
 
  return res;
292
 
}