~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/enum.cc

  • Committer: Brian Aker
  • Date: 2009-02-10 00:14:40 UTC
  • Revision ID: brian@tangent.org-20090210001440-qjg8eofh3h93064b
Adding Multi-threaded Scheduler into the system.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#include <config.h>
22
 
#include <boost/lexical_cast.hpp>
 
21
 
 
22
#include <drizzled/server_includes.h>
23
23
#include <drizzled/field/enum.h>
24
24
#include <drizzled/error.h>
25
25
#include <drizzled/table.h>
26
26
#include <drizzled/session.h>
27
 
#include <drizzled/strfunc.h>
28
 
#include <drizzled/typelib.h>
29
 
 
30
 
#include <sstream>
31
 
#include <string>
32
 
 
33
 
namespace drizzled
34
 
{
35
27
 
36
28
/****************************************************************************
37
29
** enum type.
39
31
** If one uses this string in a number context one gets the type number.
40
32
****************************************************************************/
41
33
 
 
34
enum ha_base_keytype Field_enum::key_type() const
 
35
{
 
36
  switch (packlength) {
 
37
  default: return HA_KEYTYPE_BINARY;
 
38
  case 2: assert(1);
 
39
  case 3: assert(1);
 
40
  case 4: return HA_KEYTYPE_ULONG_INT;
 
41
  case 8: return HA_KEYTYPE_ULONGLONG;
 
42
  }
 
43
}
 
44
 
42
45
void Field_enum::store_type(uint64_t value)
43
46
{
44
 
  value--; /* we store as starting from 0, although SQL starts from 1 */
45
 
 
46
 
#ifdef WORDS_BIGENDIAN
47
 
  if (getTable()->getShare()->db_low_byte_first)
48
 
  {
49
 
    int4store(ptr, (unsigned short) value);
50
 
  }
51
 
  else
52
 
#endif
53
 
    longstore(ptr, (unsigned short) value);
 
47
  switch (packlength) {
 
48
  case 1: ptr[0]= (unsigned char) value;  break;
 
49
  case 2:
 
50
#ifdef WORDS_BIGENDIAN
 
51
  if (table->s->db_low_byte_first)
 
52
  {
 
53
    int2store(ptr,(unsigned short) value);
 
54
  }
 
55
  else
 
56
#endif
 
57
    shortstore(ptr,(unsigned short) value);
 
58
  break;
 
59
  case 3: int3store(ptr,(long) value); break;
 
60
  case 4:
 
61
#ifdef WORDS_BIGENDIAN
 
62
  if (table->s->db_low_byte_first)
 
63
  {
 
64
    int4store(ptr,value);
 
65
  }
 
66
  else
 
67
#endif
 
68
    longstore(ptr,(long) value);
 
69
  break;
 
70
  case 8:
 
71
#ifdef WORDS_BIGENDIAN
 
72
  if (table->s->db_low_byte_first)
 
73
  {
 
74
    int8store(ptr,value);
 
75
  }
 
76
  else
 
77
#endif
 
78
    int64_tstore(ptr,value); break;
 
79
  }
54
80
}
55
81
 
 
82
 
56
83
/**
57
 
 * Given a supplied string, looks up the string in the internal typelib
58
 
 * and stores the found key.  Upon not finding an entry in the typelib,
59
 
 * we always throw an error.
60
 
 */
61
 
int Field_enum::store(const char *from, uint32_t length, const CHARSET_INFO * const)
 
84
  @note
 
85
    Storing a empty string in a enum field gives a warning
 
86
    (if there isn't a empty value in the enum)
 
87
*/
 
88
 
 
89
int Field_enum::store(const char *from, uint32_t length, const CHARSET_INFO * const cs)
62
90
{
63
 
  uint32_t tmp;
 
91
  int err= 0;
 
92
  uint32_t not_used;
 
93
  char buff[STRING_BUFFER_USUAL_SIZE];
 
94
  String tmpstr(buff,sizeof(buff), &my_charset_bin);
64
95
 
65
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
 
96
  /* Convert character set if necessary */
 
97
  if (String::needs_conversion(length, cs, field_charset, &not_used))
 
98
  {
 
99
    uint32_t dummy_errors;
 
100
    tmpstr.copy(from, length, cs, field_charset, &dummy_errors);
 
101
    from= tmpstr.ptr();
 
102
    length=  tmpstr.length();
 
103
  }
66
104
 
67
105
  /* Remove end space */
68
106
  length= field_charset->cset->lengthsp(field_charset, from, length);
69
 
  tmp= typelib->find_type2(from, length, field_charset);
70
 
  if (! tmp)
 
107
  uint32_t tmp=find_type2(typelib, from, length, field_charset);
 
108
  if (!tmp)
71
109
  {
72
 
    if (length < 6) /* Can't be more than 99999 enums */
 
110
    if (length < 6) // Can't be more than 99999 enums
73
111
    {
74
112
      /* This is for reading numbers with LOAD DATA INFILE */
75
 
      /* Convert the string to an integer using stringstream */
76
 
      std::stringstream ss;
77
 
      ss << from;
78
 
      ss >> tmp;
79
 
 
80
 
      if (tmp == 0 || tmp > typelib->count)
 
113
      char *end;
 
114
      tmp=(uint) my_strntoul(cs,from,length,10,&end,&err);
 
115
      if (err || end != from+length || tmp > typelib->count)
81
116
      {
82
 
        my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
83
 
        return 1;
 
117
        tmp=0;
 
118
        set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
84
119
      }
 
120
      if (!table->in_use->count_cuted_fields)
 
121
        err= 0;
85
122
    }
86
123
    else
87
 
    {
88
 
      my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
89
 
      return 1;
90
 
    }
 
124
      set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
91
125
  }
92
126
  store_type((uint64_t) tmp);
93
 
  return 0;
94
 
}
95
 
 
96
 
int Field_enum::store(double from)
97
 
{
98
 
  return Field_enum::store((int64_t) from, false);
99
 
}
100
 
 
101
 
/**
102
 
 * @note MySQL allows 0 values, saying that 0 is "the index of the
103
 
 * blank string error", whatever that means.  Uhm, Drizzle doesn't
104
 
 * allow this.  To store an ENUM column value using an integer, you
105
 
 * must specify the 1-based index of the enum column definition's
106
 
 * key.
107
 
 */
108
 
int Field_enum::store(int64_t from, bool)
109
 
{
110
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
111
 
 
112
 
  if (from <= 0 || (uint64_t) from > typelib->count)
 
127
  return err;
 
128
}
 
129
 
 
130
 
 
131
int Field_enum::store(double nr)
 
132
{
 
133
  return Field_enum::store((int64_t) nr, false);
 
134
}
 
135
 
 
136
 
 
137
int Field_enum::store(int64_t nr,
 
138
                      bool )
 
139
{
 
140
  int error= 0;
 
141
  if ((uint64_t) nr > typelib->count || nr == 0)
113
142
  {
114
 
    /* Convert the integer to a string using boost::lexical_cast */
115
 
    std::string tmp(boost::lexical_cast<std::string>(from));
116
 
 
117
 
    my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), tmp.c_str());
118
 
    return 1;
 
143
    set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
144
    if (nr != 0 || table->in_use->count_cuted_fields)
 
145
    {
 
146
      nr= 0;
 
147
      error= 1;
 
148
    }
119
149
  }
120
 
  store_type((uint64_t) (uint32_t) from);
121
 
  return 0;
 
150
  store_type((uint64_t) (uint) nr);
 
151
  return error;
122
152
}
123
153
 
124
 
double Field_enum::val_real(void) const
 
154
 
 
155
double Field_enum::val_real(void)
125
156
{
126
157
  return (double) Field_enum::val_int();
127
158
}
128
159
 
129
 
int64_t Field_enum::val_int(void) const
130
 
{
131
 
  ASSERT_COLUMN_MARKED_FOR_READ;
132
 
 
133
 
  uint16_t tmp;
134
 
#ifdef WORDS_BIGENDIAN
135
 
  if (getTable()->getShare()->db_low_byte_first)
136
 
    tmp= sint4korr(ptr);
137
 
  else
138
 
#endif
139
 
    longget(tmp,ptr);
140
 
  return ((int64_t) tmp) + 1; /* SQL is from 1, we store from 0 */
141
 
}
142
 
 
143
 
String *Field_enum::val_str(String *, String *val_ptr) const
144
 
{
145
 
  uint32_t tmp=(uint32_t) Field_enum::val_int();
146
 
 
147
 
  ASSERT_COLUMN_MARKED_FOR_READ;
148
 
 
149
 
  if (not tmp || tmp > typelib->count)
150
 
  {
 
160
 
 
161
int64_t Field_enum::val_int(void)
 
162
{
 
163
  switch (packlength) {
 
164
  case 1:
 
165
    return (int64_t) ptr[0];
 
166
  case 2:
 
167
  {
 
168
    uint16_t tmp;
 
169
#ifdef WORDS_BIGENDIAN
 
170
    if (table->s->db_low_byte_first)
 
171
      tmp=sint2korr(ptr);
 
172
    else
 
173
#endif
 
174
      shortget(tmp,ptr);
 
175
    return (int64_t) tmp;
 
176
  }
 
177
  case 3:
 
178
    return (int64_t) uint3korr(ptr);
 
179
  case 4:
 
180
  {
 
181
    uint32_t tmp;
 
182
#ifdef WORDS_BIGENDIAN
 
183
    if (table->s->db_low_byte_first)
 
184
      tmp=uint4korr(ptr);
 
185
    else
 
186
#endif
 
187
      longget(tmp,ptr);
 
188
    return (int64_t) tmp;
 
189
  }
 
190
  case 8:
 
191
  {
 
192
    int64_t tmp;
 
193
#ifdef WORDS_BIGENDIAN
 
194
    if (table->s->db_low_byte_first)
 
195
      tmp=sint8korr(ptr);
 
196
    else
 
197
#endif
 
198
      int64_tget(tmp,ptr);
 
199
    return tmp;
 
200
  }
 
201
  }
 
202
  return 0;                                     // impossible
 
203
}
 
204
 
 
205
 
 
206
/**
 
207
   Save the field metadata for enum fields.
 
208
 
 
209
   Saves the real type in the first byte and the pack length in the
 
210
   second byte of the field metadata array at index of *metadata_ptr and
 
211
   *(metadata_ptr + 1).
 
212
 
 
213
   @param   metadata_ptr   First byte of field metadata
 
214
 
 
215
   @returns number of bytes written to metadata_ptr
 
216
*/
 
217
int Field_enum::do_save_field_metadata(unsigned char *metadata_ptr)
 
218
{
 
219
  *metadata_ptr= real_type();
 
220
  *(metadata_ptr + 1)= pack_length();
 
221
  return 2;
 
222
}
 
223
 
 
224
 
 
225
String *Field_enum::val_str(String *,
 
226
                            String *val_ptr)
 
227
{
 
228
  uint32_t tmp=(uint) Field_enum::val_int();
 
229
  if (!tmp || tmp > typelib->count)
151
230
    val_ptr->set("", 0, field_charset);
152
 
  }
153
231
  else
154
 
  {
155
 
    val_ptr->set((const char*) typelib->type_names[tmp-1], typelib->type_lengths[tmp-1], field_charset);
156
 
  }
157
 
 
 
232
    val_ptr->set((const char*) typelib->type_names[tmp-1],
 
233
                 typelib->type_lengths[tmp-1],
 
234
                 field_charset);
158
235
  return val_ptr;
159
236
}
160
237
 
162
239
{
163
240
  unsigned char *old= ptr;
164
241
  ptr= (unsigned char*) a_ptr;
165
 
  uint64_t a= Field_enum::val_int();
 
242
  uint64_t a=Field_enum::val_int();
166
243
  ptr= (unsigned char*) b_ptr;
167
 
  uint64_t b= Field_enum::val_int();
 
244
  uint64_t b=Field_enum::val_int();
168
245
  ptr= old;
169
246
  return (a < b) ? -1 : (a > b) ? 1 : 0;
170
247
}
171
248
 
172
249
void Field_enum::sort_string(unsigned char *to,uint32_t )
173
250
{
174
 
  uint64_t value=Field_enum::val_int()-1; /* SQL is 1 based, stored as 0 based*/
175
 
  to+=pack_length() -1;
176
 
  for (uint32_t i=0 ; i < pack_length() ; i++)
 
251
  uint64_t value=Field_enum::val_int();
 
252
  to+=packlength-1;
 
253
  for (uint32_t i=0 ; i < packlength ; i++)
177
254
  {
178
255
    *to-- = (unsigned char) (value & 255);
179
256
    value>>=8;
180
257
  }
181
258
}
182
259
 
 
260
 
183
261
void Field_enum::sql_type(String &res) const
184
262
{
185
263
  char buffer[255];
192
270
  uint32_t *len= typelib->type_lengths;
193
271
  for (const char **pos= typelib->type_names; *pos; pos++, len++)
194
272
  {
195
 
    size_t dummy_errors;
 
273
    uint32_t dummy_errors;
196
274
    if (flag)
197
275
      res.append(',');
198
276
    /* convert to res.charset() == utf8, then quote */
203
281
  res.append(')');
204
282
}
205
283
 
206
 
Field *Field_enum::new_field(memory::Root *root, Table *new_table,
 
284
 
 
285
Field *Field_enum::new_field(MEM_ROOT *root, Table *new_table,
207
286
                             bool keep_type)
208
287
{
209
288
  Field_enum *res= (Field_enum*) Field::new_field(root, new_table, keep_type);
210
289
  if (res)
211
 
  {
212
 
    res->typelib= typelib->copy_typelib(root);
213
 
  }
 
290
    res->typelib= copy_typelib(root, typelib);
214
291
  return res;
215
292
}
216
 
 
217
 
} /* namespace drizzled */