~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/enum.cc

  • Committer: Monty Taylor
  • Date: 2008-09-15 17:24:04 UTC
  • Revision ID: monty@inaugust.com-20080915172404-ygh6hiyu0q7qpa9x
Removed strndup calls.

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