~drizzle-trunk/drizzle/development

466 by Monty Taylor
Fixed modelines... these files are c++.
1
/* - mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
438.4.1 by Lee
breaking out enum field classes
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
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
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
#include <sstream>
29
#include <string>
438.4.1 by Lee
breaking out enum field classes
30
31
/****************************************************************************
32
** enum type.
33
** This is a string which only can have a selection of different values.
34
** If one uses this string in a number context one gets the type number.
35
****************************************************************************/
36
37
enum ha_base_keytype Field_enum::key_type() const
38
{
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
39
  switch (packlength) 
40
  {
41
    default: return HA_KEYTYPE_BINARY;
42
    case 2: assert(1);
43
    case 3: assert(1);
44
    case 4: return HA_KEYTYPE_ULONG_INT;
45
    case 8: return HA_KEYTYPE_ULONGLONG;
438.4.1 by Lee
breaking out enum field classes
46
  }
47
}
48
49
void Field_enum::store_type(uint64_t value)
50
{
51
  switch (packlength) {
481 by Brian Aker
Remove all of uchar.
52
  case 1: ptr[0]= (unsigned char) value;  break;
438.4.1 by Lee
breaking out enum field classes
53
  case 2:
54
#ifdef WORDS_BIGENDIAN
55
  if (table->s->db_low_byte_first)
56
  {
57
    int2store(ptr,(unsigned short) value);
58
  }
59
  else
60
#endif
61
    shortstore(ptr,(unsigned short) value);
62
  break;
63
  case 3: int3store(ptr,(long) value); break;
64
  case 4:
65
#ifdef WORDS_BIGENDIAN
66
  if (table->s->db_low_byte_first)
67
  {
68
    int4store(ptr,value);
69
  }
70
  else
71
#endif
72
    longstore(ptr,(long) value);
73
  break;
74
  case 8:
75
#ifdef WORDS_BIGENDIAN
76
  if (table->s->db_low_byte_first)
77
  {
78
    int8store(ptr,value);
79
  }
80
  else
81
#endif
82
    int64_tstore(ptr,value); break;
83
  }
84
}
85
86
/**
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
87
 * Given a supplied string, looks up the string in the internal typelib
88
 * and stores the found key.  Upon not finding an entry in the typelib, 
89
 * we always throw an error.
90
 */
91
int Field_enum::store(const char *from, uint32_t length, const CHARSET_INFO * const)
438.4.1 by Lee
breaking out enum field classes
92
{
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
93
  uint32_t tmp;
438.4.1 by Lee
breaking out enum field classes
94
95
  /* Remove end space */
96
  length= field_charset->cset->lengthsp(field_charset, from, length);
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
97
  tmp= find_type2(typelib, from, length, field_charset);
98
  if (! tmp)
438.4.1 by Lee
breaking out enum field classes
99
  {
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
100
    if (length < 6) /* Can't be more than 99999 enums */
438.4.1 by Lee
breaking out enum field classes
101
    {
102
      /* This is for reading numbers with LOAD DATA INFILE */
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
103
      /* Convert the string to an integer using stringstream */
104
      std::stringstream ss;
105
      ss << from;
106
      ss >> tmp;
107
108
      if (tmp == 0 || tmp > typelib->count)
438.4.1 by Lee
breaking out enum field classes
109
      {
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
110
        my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
111
        return 1;
438.4.1 by Lee
breaking out enum field classes
112
      }
113
    }
114
    else
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
115
    {
116
      my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
117
      return 1;
118
    }
438.4.1 by Lee
breaking out enum field classes
119
  }
120
  store_type((uint64_t) tmp);
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
121
  return 0;
122
}
123
124
int Field_enum::store(double from)
125
{
126
  return Field_enum::store((int64_t) from, false);
127
}
128
129
/**
130
 * @note MySQL allows 0 values, saying that 0 is "the index of the
131
 * blank string error", whatever that means.  Uhm, Drizzle doesn't
132
 * allow this.  To store an ENUM column value using an integer, you
133
 * must specify the 1-based index of the enum column definition's 
134
 * key.
135
 */
136
int Field_enum::store(int64_t from, bool)
137
{
138
  if (from <= 0 || (uint64_t) from > typelib->count)
438.4.1 by Lee
breaking out enum field classes
139
  {
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
140
    /* Convert the integer to a string using stringstream */
141
    std::stringstream ss;
142
    std::string tmp;
143
    ss << from; ss >> tmp;
144
145
    my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), tmp.c_str());
146
    return 1;
438.4.1 by Lee
breaking out enum field classes
147
  }
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
148
  store_type((uint64_t) (uint32_t) from);
149
  return 0;
438.4.1 by Lee
breaking out enum field classes
150
}
151
152
double Field_enum::val_real(void)
153
{
154
  return (double) Field_enum::val_int();
155
}
156
157
int64_t Field_enum::val_int(void)
158
{
159
  switch (packlength) {
160
  case 1:
161
    return (int64_t) ptr[0];
162
  case 2:
163
  {
164
    uint16_t tmp;
165
#ifdef WORDS_BIGENDIAN
166
    if (table->s->db_low_byte_first)
167
      tmp=sint2korr(ptr);
168
    else
169
#endif
170
      shortget(tmp,ptr);
171
    return (int64_t) tmp;
172
  }
173
  case 3:
174
    return (int64_t) uint3korr(ptr);
175
  case 4:
176
  {
177
    uint32_t tmp;
178
#ifdef WORDS_BIGENDIAN
179
    if (table->s->db_low_byte_first)
180
      tmp=uint4korr(ptr);
181
    else
182
#endif
183
      longget(tmp,ptr);
184
    return (int64_t) tmp;
185
  }
186
  case 8:
187
  {
188
    int64_t tmp;
189
#ifdef WORDS_BIGENDIAN
190
    if (table->s->db_low_byte_first)
191
      tmp=sint8korr(ptr);
192
    else
193
#endif
194
      int64_tget(tmp,ptr);
195
    return tmp;
196
  }
197
  }
198
  return 0;					// impossible
199
}
200
201
/**
202
   Save the field metadata for enum fields.
203
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
204
   Saves the real type in the first byte and the pack length in the
438.4.1 by Lee
breaking out enum field classes
205
   second byte of the field metadata array at index of *metadata_ptr and
206
   *(metadata_ptr + 1).
207
208
   @param   metadata_ptr   First byte of field metadata
209
210
   @returns number of bytes written to metadata_ptr
211
*/
481 by Brian Aker
Remove all of uchar.
212
int Field_enum::do_save_field_metadata(unsigned char *metadata_ptr)
438.4.1 by Lee
breaking out enum field classes
213
{
214
  *metadata_ptr= real_type();
215
  *(metadata_ptr + 1)= pack_length();
216
  return 2;
217
}
218
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
219
String *Field_enum::val_str(String *, String *val_ptr)
438.4.1 by Lee
breaking out enum field classes
220
{
895 by Brian Aker
Completion (?) of uint conversion.
221
  uint32_t tmp=(uint32_t) Field_enum::val_int();
438.4.1 by Lee
breaking out enum field classes
222
  if (!tmp || tmp > typelib->count)
223
    val_ptr->set("", 0, field_charset);
224
  else
225
    val_ptr->set((const char*) typelib->type_names[tmp-1],
226
		 typelib->type_lengths[tmp-1],
227
		 field_charset);
228
  return val_ptr;
229
}
230
481 by Brian Aker
Remove all of uchar.
231
int Field_enum::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
438.4.1 by Lee
breaking out enum field classes
232
{
481 by Brian Aker
Remove all of uchar.
233
  unsigned char *old= ptr;
234
  ptr= (unsigned char*) a_ptr;
438.4.1 by Lee
breaking out enum field classes
235
  uint64_t a=Field_enum::val_int();
481 by Brian Aker
Remove all of uchar.
236
  ptr= (unsigned char*) b_ptr;
438.4.1 by Lee
breaking out enum field classes
237
  uint64_t b=Field_enum::val_int();
238
  ptr= old;
239
  return (a < b) ? -1 : (a > b) ? 1 : 0;
240
}
241
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
242
void Field_enum::sort_string(unsigned char *to,uint32_t )
438.4.1 by Lee
breaking out enum field classes
243
{
244
  uint64_t value=Field_enum::val_int();
245
  to+=packlength-1;
482 by Brian Aker
Remove uint.
246
  for (uint32_t i=0 ; i < packlength ; i++)
438.4.1 by Lee
breaking out enum field classes
247
  {
481 by Brian Aker
Remove all of uchar.
248
    *to-- = (unsigned char) (value & 255);
438.4.1 by Lee
breaking out enum field classes
249
    value>>=8;
250
  }
251
}
252
253
void Field_enum::sql_type(String &res) const
254
{
255
  char buffer[255];
256
  String enum_item(buffer, sizeof(buffer), res.charset());
257
258
  res.length(0);
259
  res.append(STRING_WITH_LEN("enum("));
260
261
  bool flag=0;
482 by Brian Aker
Remove uint.
262
  uint32_t *len= typelib->type_lengths;
438.4.1 by Lee
breaking out enum field classes
263
  for (const char **pos= typelib->type_names; *pos; pos++, len++)
264
  {
482 by Brian Aker
Remove uint.
265
    uint32_t dummy_errors;
438.4.1 by Lee
breaking out enum field classes
266
    if (flag)
267
      res.append(',');
268
    /* convert to res.charset() == utf8, then quote */
269
    enum_item.copy(*pos, *len, charset(), res.charset(), &dummy_errors);
814.1.1 by Jay Pipes
Fix for Bug 314502 "show create table crashes with multi-byte character in enum description"
270
    append_unescaped(&res, enum_item.c_ptr(), enum_item.length());
438.4.1 by Lee
breaking out enum field classes
271
    flag= 1;
272
  }
273
  res.append(')');
274
}
275
276
Field *Field_enum::new_field(MEM_ROOT *root, Table *new_table,
277
                             bool keep_type)
278
{
279
  Field_enum *res= (Field_enum*) Field::new_field(root, new_table, keep_type);
280
  if (res)
281
    res->typelib= copy_typelib(root, typelib);
282
  return res;
283
}