1
/* - mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 MySQL
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.
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.
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
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"
31
/****************************************************************************
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
****************************************************************************/
37
enum ha_base_keytype Field_enum::key_type() const
41
default: return HA_KEYTYPE_BINARY;
44
case 4: return HA_KEYTYPE_ULONG_INT;
45
case 8: return HA_KEYTYPE_ULONGLONG;
49
void Field_enum::store_type(uint64_t value)
52
case 1: ptr[0]= (unsigned char) value; break;
54
#ifdef WORDS_BIGENDIAN
55
if (table->s->db_low_byte_first)
57
int2store(ptr,(unsigned short) value);
61
shortstore(ptr,(unsigned short) value);
63
case 3: int3store(ptr,(long) value); break;
65
#ifdef WORDS_BIGENDIAN
66
if (table->s->db_low_byte_first)
72
longstore(ptr,(long) value);
75
#ifdef WORDS_BIGENDIAN
76
if (table->s->db_low_byte_first)
82
int64_tstore(ptr,value); break;
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.
91
int Field_enum::store(const char *from, uint32_t length, const CHARSET_INFO * const)
95
ASSERT_COLUMN_MARKED_FOR_WRITE;
97
/* Remove end space */
98
length= field_charset->cset->lengthsp(field_charset, from, length);
99
tmp= find_type2(typelib, from, length, field_charset);
102
if (length < 6) /* Can't be more than 99999 enums */
104
/* This is for reading numbers with LOAD DATA INFILE */
105
/* Convert the string to an integer using stringstream */
106
std::stringstream ss;
110
if (tmp == 0 || tmp > typelib->count)
112
my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
118
my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
122
store_type((uint64_t) tmp);
126
int Field_enum::store(double from)
128
return Field_enum::store((int64_t) from, false);
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
138
int Field_enum::store(int64_t from, bool)
140
ASSERT_COLUMN_MARKED_FOR_WRITE;
142
if (from <= 0 || (uint64_t) from > typelib->count)
144
/* Convert the integer to a string using stringstream */
145
std::stringstream ss;
147
ss << from; ss >> tmp;
149
my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), tmp.c_str());
152
store_type((uint64_t) (uint32_t) from);
156
double Field_enum::val_real(void)
158
return (double) Field_enum::val_int();
161
int64_t Field_enum::val_int(void)
163
ASSERT_COLUMN_MARKED_FOR_READ;
165
switch (packlength) {
167
return (int64_t) ptr[0];
171
#ifdef WORDS_BIGENDIAN
172
if (table->s->db_low_byte_first)
177
return (int64_t) tmp;
180
return (int64_t) uint3korr(ptr);
184
#ifdef WORDS_BIGENDIAN
185
if (table->s->db_low_byte_first)
190
return (int64_t) tmp;
195
#ifdef WORDS_BIGENDIAN
196
if (table->s->db_low_byte_first)
204
return 0; // impossible
208
Save the field metadata for enum fields.
210
Saves the real type in the first byte and the pack length in the
211
second byte of the field metadata array at index of *metadata_ptr and
214
@param metadata_ptr First byte of field metadata
216
@returns number of bytes written to metadata_ptr
218
int Field_enum::do_save_field_metadata(unsigned char *metadata_ptr)
220
*metadata_ptr= real_type();
221
*(metadata_ptr + 1)= pack_length();
225
String *Field_enum::val_str(String *, String *val_ptr)
227
uint32_t tmp=(uint32_t) Field_enum::val_int();
229
ASSERT_COLUMN_MARKED_FOR_READ;
231
if (!tmp || tmp > typelib->count)
232
val_ptr->set("", 0, field_charset);
234
val_ptr->set((const char*) typelib->type_names[tmp-1],
235
typelib->type_lengths[tmp-1],
240
int Field_enum::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
242
unsigned char *old= ptr;
243
ptr= (unsigned char*) a_ptr;
244
uint64_t a=Field_enum::val_int();
245
ptr= (unsigned char*) b_ptr;
246
uint64_t b=Field_enum::val_int();
248
return (a < b) ? -1 : (a > b) ? 1 : 0;
251
void Field_enum::sort_string(unsigned char *to,uint32_t )
253
uint64_t value=Field_enum::val_int();
255
for (uint32_t i=0 ; i < packlength ; i++)
257
*to-- = (unsigned char) (value & 255);
262
void Field_enum::sql_type(String &res) const
265
String enum_item(buffer, sizeof(buffer), res.charset());
268
res.append(STRING_WITH_LEN("enum("));
271
uint32_t *len= typelib->type_lengths;
272
for (const char **pos= typelib->type_names; *pos; pos++, len++)
274
uint32_t dummy_errors;
277
/* convert to res.charset() == utf8, then quote */
278
enum_item.copy(*pos, *len, charset(), res.charset(), &dummy_errors);
279
append_unescaped(&res, enum_item.c_ptr(), enum_item.length());
285
Field *Field_enum::new_field(MEM_ROOT *root, Table *new_table,
288
Field_enum *res= (Field_enum*) Field::new_field(root, new_table, keep_type);
290
res->typelib= copy_typelib(root, typelib);