~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/enum.cc

  • Committer: Monty Taylor
  • Date: 2008-10-04 03:15:20 UTC
  • mfrom: (438.4.1 drizzle-clean-code)
  • Revision ID: monty@inaugust.com-20081004031520-j3d38cge8tlrwuhh
MergedĀ fromĀ Lee.

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
#ifdef USE_PRAGMA_IMPLEMENTATION
 
22
#pragma implementation                          // gcc: Class implementation
 
23
#endif
 
24
 
 
25
#include <drizzled/server_includes.h>
 
26
#include <drizzled/field/enum.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]= (uchar) 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, uint 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
    uint 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
  uint 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(uchar *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
  uint 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 uchar *a_ptr, const uchar *b_ptr)
 
239
{
 
240
  uchar *old= ptr;
 
241
  ptr= (uchar*) a_ptr;
 
242
  uint64_t a=Field_enum::val_int();
 
243
  ptr= (uchar*) 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(uchar *to,uint length __attribute__((unused)))
 
250
{
 
251
  uint64_t value=Field_enum::val_int();
 
252
  to+=packlength-1;
 
253
  for (uint i=0 ; i < packlength ; i++)
 
254
  {
 
255
    *to-- = (uchar) (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
  uint *len= typelib->type_lengths;
 
271
  for (const char **pos= typelib->type_names; *pos; pos++, len++)
 
272
  {
 
273
    uint 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
}
 
293
 
 
294
 
 
295
/**
 
296
  @retval
 
297
    1  if the fields are equally defined
 
298
  @retval
 
299
    0  if the fields are unequally defined
 
300
*/