~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/enum.cc

  • Committer: Monty Taylor
  • Date: 2008-07-05 22:08:52 UTC
  • mto: This revision was merged to the branch mainline in revision 77.
  • Revision ID: monty@inaugust.com-20080705220852-cqd9t6tfkhvlcf73
Removed HAVE_LONG_LONG, as this is now assumed.

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