~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
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
95
  ASSERT_COLUMN_MARKED_FOR_WRITE;
96
438.4.1 by Lee
breaking out enum field classes
97
  /* Remove end space */
98
  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
99
  tmp= find_type2(typelib, from, length, field_charset);
100
  if (! tmp)
438.4.1 by Lee
breaking out enum field classes
101
  {
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
102
    if (length < 6) /* Can't be more than 99999 enums */
438.4.1 by Lee
breaking out enum field classes
103
    {
104
      /* 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
105
      /* Convert the string to an integer using stringstream */
106
      std::stringstream ss;
107
      ss << from;
108
      ss >> tmp;
109
110
      if (tmp == 0 || tmp > typelib->count)
438.4.1 by Lee
breaking out enum field classes
111
      {
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
112
        my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
113
        return 1;
438.4.1 by Lee
breaking out enum field classes
114
      }
115
    }
116
    else
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
117
    {
118
      my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
119
      return 1;
120
    }
438.4.1 by Lee
breaking out enum field classes
121
  }
122
  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
123
  return 0;
124
}
125
126
int Field_enum::store(double from)
127
{
128
  return Field_enum::store((int64_t) from, false);
129
}
130
131
/**
132
 * @note MySQL allows 0 values, saying that 0 is "the index of the
133
 * blank string error", whatever that means.  Uhm, Drizzle doesn't
134
 * allow this.  To store an ENUM column value using an integer, you
135
 * must specify the 1-based index of the enum column definition's 
136
 * key.
137
 */
138
int Field_enum::store(int64_t from, bool)
139
{
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
140
  ASSERT_COLUMN_MARKED_FOR_WRITE;
141
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
142
  if (from <= 0 || (uint64_t) from > typelib->count)
438.4.1 by Lee
breaking out enum field classes
143
  {
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
144
    /* Convert the integer to a string using stringstream */
145
    std::stringstream ss;
146
    std::string tmp;
147
    ss << from; ss >> tmp;
148
149
    my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), tmp.c_str());
150
    return 1;
438.4.1 by Lee
breaking out enum field classes
151
  }
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
152
  store_type((uint64_t) (uint32_t) from);
153
  return 0;
438.4.1 by Lee
breaking out enum field classes
154
}
155
156
double Field_enum::val_real(void)
157
{
158
  return (double) Field_enum::val_int();
159
}
160
161
int64_t Field_enum::val_int(void)
162
{
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
163
  ASSERT_COLUMN_MARKED_FOR_READ;
164
438.4.1 by Lee
breaking out enum field classes
165
  switch (packlength) {
166
  case 1:
167
    return (int64_t) ptr[0];
168
  case 2:
169
  {
170
    uint16_t tmp;
171
#ifdef WORDS_BIGENDIAN
172
    if (table->s->db_low_byte_first)
173
      tmp=sint2korr(ptr);
174
    else
175
#endif
176
      shortget(tmp,ptr);
177
    return (int64_t) tmp;
178
  }
179
  case 3:
180
    return (int64_t) uint3korr(ptr);
181
  case 4:
182
  {
183
    uint32_t tmp;
184
#ifdef WORDS_BIGENDIAN
185
    if (table->s->db_low_byte_first)
186
      tmp=uint4korr(ptr);
187
    else
188
#endif
189
      longget(tmp,ptr);
190
    return (int64_t) tmp;
191
  }
192
  case 8:
193
  {
194
    int64_t tmp;
195
#ifdef WORDS_BIGENDIAN
196
    if (table->s->db_low_byte_first)
197
      tmp=sint8korr(ptr);
198
    else
199
#endif
200
      int64_tget(tmp,ptr);
201
    return tmp;
202
  }
203
  }
204
  return 0;					// impossible
205
}
206
207
/**
208
   Save the field metadata for enum fields.
209
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
210
   Saves the real type in the first byte and the pack length in the
438.4.1 by Lee
breaking out enum field classes
211
   second byte of the field metadata array at index of *metadata_ptr and
212
   *(metadata_ptr + 1).
213
214
   @param   metadata_ptr   First byte of field metadata
215
216
   @returns number of bytes written to metadata_ptr
217
*/
481 by Brian Aker
Remove all of uchar.
218
int Field_enum::do_save_field_metadata(unsigned char *metadata_ptr)
438.4.1 by Lee
breaking out enum field classes
219
{
220
  *metadata_ptr= real_type();
221
  *(metadata_ptr + 1)= pack_length();
222
  return 2;
223
}
224
934.4.1 by Jay Pipes
Fixes ENUM field type to throw an error on bad data input. 0 is now not
225
String *Field_enum::val_str(String *, String *val_ptr)
438.4.1 by Lee
breaking out enum field classes
226
{
895 by Brian Aker
Completion (?) of uint conversion.
227
  uint32_t tmp=(uint32_t) Field_enum::val_int();
1089.1.3 by Brian Aker
Fix protobuf to release memory. Add in assert() for wrong column usage. Fix
228
229
  ASSERT_COLUMN_MARKED_FOR_READ;
230
438.4.1 by Lee
breaking out enum field classes
231
  if (!tmp || tmp > typelib->count)
232
    val_ptr->set("", 0, field_charset);
233
  else
234
    val_ptr->set((const char*) typelib->type_names[tmp-1],
235
		 typelib->type_lengths[tmp-1],
236
		 field_charset);
237
  return val_ptr;
238
}
239
481 by Brian Aker
Remove all of uchar.
240
int Field_enum::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
438.4.1 by Lee
breaking out enum field classes
241
{
481 by Brian Aker
Remove all of uchar.
242
  unsigned char *old= ptr;
243
  ptr= (unsigned char*) a_ptr;
438.4.1 by Lee
breaking out enum field classes
244
  uint64_t a=Field_enum::val_int();
481 by Brian Aker
Remove all of uchar.
245
  ptr= (unsigned char*) b_ptr;
438.4.1 by Lee
breaking out enum field classes
246
  uint64_t b=Field_enum::val_int();
247
  ptr= old;
248
  return (a < b) ? -1 : (a > b) ? 1 : 0;
249
}
250
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
251
void Field_enum::sort_string(unsigned char *to,uint32_t )
438.4.1 by Lee
breaking out enum field classes
252
{
253
  uint64_t value=Field_enum::val_int();
254
  to+=packlength-1;
482 by Brian Aker
Remove uint.
255
  for (uint32_t i=0 ; i < packlength ; i++)
438.4.1 by Lee
breaking out enum field classes
256
  {
481 by Brian Aker
Remove all of uchar.
257
    *to-- = (unsigned char) (value & 255);
438.4.1 by Lee
breaking out enum field classes
258
    value>>=8;
259
  }
260
}
261
262
void Field_enum::sql_type(String &res) const
263
{
264
  char buffer[255];
265
  String enum_item(buffer, sizeof(buffer), res.charset());
266
267
  res.length(0);
268
  res.append(STRING_WITH_LEN("enum("));
269
270
  bool flag=0;
482 by Brian Aker
Remove uint.
271
  uint32_t *len= typelib->type_lengths;
438.4.1 by Lee
breaking out enum field classes
272
  for (const char **pos= typelib->type_names; *pos; pos++, len++)
273
  {
482 by Brian Aker
Remove uint.
274
    uint32_t dummy_errors;
438.4.1 by Lee
breaking out enum field classes
275
    if (flag)
276
      res.append(',');
277
    /* convert to res.charset() == utf8, then quote */
278
    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"
279
    append_unescaped(&res, enum_item.c_ptr(), enum_item.length());
438.4.1 by Lee
breaking out enum field classes
280
    flag= 1;
281
  }
282
  res.append(')');
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
}