~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/enum.cc

Merged in latest plugin-slot-reorg.

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
 
#ifdef USE_PRAGMA_IMPLEMENTATION
22
 
#pragma implementation                          // gcc: Class implementation
23
 
#endif
24
 
 
25
 
#include <drizzled/server_includes.h>
26
 
#include <drizzled/field/enum.h>
 
21
 
 
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>
27
30
 
28
31
/****************************************************************************
29
32
** enum type.
33
36
 
34
37
enum ha_base_keytype Field_enum::key_type() const
35
38
{
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;
 
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;
42
46
  }
43
47
}
44
48
 
79
83
  }
80
84
}
81
85
 
82
 
 
83
86
/**
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)
 
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)
90
92
{
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);
 
93
  uint32_t tmp;
95
94
 
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
 
  }
 
95
  ASSERT_COLUMN_MARKED_FOR_WRITE;
104
96
 
105
97
  /* Remove end space */
106
98
  length= field_charset->cset->lengthsp(field_charset, from, length);
107
 
  uint32_t tmp=find_type2(typelib, from, length, field_charset);
108
 
  if (!tmp)
 
99
  tmp= find_type2(typelib, from, length, field_charset);
 
100
  if (! tmp)
109
101
  {
110
 
    if (length < 6) // Can't be more than 99999 enums
 
102
    if (length < 6) /* Can't be more than 99999 enums */
111
103
    {
112
104
      /* This is for reading numbers with LOAD DATA INFILE */
113
 
      char *end;
114
 
      tmp=(uint) my_strntoul(cs,from,length,10,&end,&err);
115
 
      if (err || end != from+length || tmp > typelib->count)
 
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)
116
111
      {
117
 
        tmp=0;
118
 
        set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
112
        my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
 
113
        return 1;
119
114
      }
120
 
      if (!table->in_use->count_cuted_fields)
121
 
        err= 0;
122
115
    }
123
116
    else
124
 
      set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
117
    {
 
118
      my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
 
119
      return 1;
 
120
    }
125
121
  }
126
122
  store_type((uint64_t) tmp);
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 unsigned_val __attribute__((unused)))
139
 
{
140
 
  int error= 0;
141
 
  if ((uint64_t) nr > typelib->count || nr == 0)
 
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
{
 
140
  ASSERT_COLUMN_MARKED_FOR_WRITE;
 
141
 
 
142
  if (from <= 0 || (uint64_t) from > typelib->count)
142
143
  {
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
 
    }
 
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;
149
151
  }
150
 
  store_type((uint64_t) (uint) nr);
151
 
  return error;
 
152
  store_type((uint64_t) (uint32_t) from);
 
153
  return 0;
152
154
}
153
155
 
154
 
 
155
156
double Field_enum::val_real(void)
156
157
{
157
158
  return (double) Field_enum::val_int();
158
159
}
159
160
 
160
 
 
161
161
int64_t Field_enum::val_int(void)
162
162
{
 
163
  ASSERT_COLUMN_MARKED_FOR_READ;
 
164
 
163
165
  switch (packlength) {
164
166
  case 1:
165
167
    return (int64_t) ptr[0];
202
204
  return 0;                                     // impossible
203
205
}
204
206
 
205
 
 
206
207
/**
207
208
   Save the field metadata for enum fields.
208
209
 
209
 
   Saves the real type in the first byte and the pack length in the 
 
210
   Saves the real type in the first byte and the pack length in the
210
211
   second byte of the field metadata array at index of *metadata_ptr and
211
212
   *(metadata_ptr + 1).
212
213
 
221
222
  return 2;
222
223
}
223
224
 
224
 
 
225
 
String *Field_enum::val_str(String *val_buffer __attribute__((unused)),
226
 
                            String *val_ptr)
 
225
String *Field_enum::val_str(String *, String *val_ptr)
227
226
{
228
 
  uint32_t tmp=(uint) Field_enum::val_int();
 
227
  uint32_t tmp=(uint32_t) Field_enum::val_int();
 
228
 
 
229
  ASSERT_COLUMN_MARKED_FOR_READ;
 
230
 
229
231
  if (!tmp || tmp > typelib->count)
230
232
    val_ptr->set("", 0, field_charset);
231
233
  else
246
248
  return (a < b) ? -1 : (a > b) ? 1 : 0;
247
249
}
248
250
 
249
 
void Field_enum::sort_string(unsigned char *to,uint32_t length __attribute__((unused)))
 
251
void Field_enum::sort_string(unsigned char *to,uint32_t )
250
252
{
251
253
  uint64_t value=Field_enum::val_int();
252
254
  to+=packlength-1;
257
259
  }
258
260
}
259
261
 
260
 
 
261
262
void Field_enum::sql_type(String &res) const
262
263
{
263
264
  char buffer[255];
275
276
      res.append(',');
276
277
    /* convert to res.charset() == utf8, then quote */
277
278
    enum_item.copy(*pos, *len, charset(), res.charset(), &dummy_errors);
278
 
    append_unescaped(&res, enum_item.ptr(), enum_item.length());
 
279
    append_unescaped(&res, enum_item.c_ptr(), enum_item.length());
279
280
    flag= 1;
280
281
  }
281
282
  res.append(')');
282
283
}
283
284
 
284
 
 
285
285
Field *Field_enum::new_field(MEM_ROOT *root, Table *new_table,
286
286
                             bool keep_type)
287
287
{
290
290
    res->typelib= copy_typelib(root, typelib);
291
291
  return res;
292
292
}
293
 
 
294
 
 
295
 
/**
296
 
  @retval
297
 
    1  if the fields are equally defined
298
 
  @retval
299
 
    0  if the fields are unequally defined
300
 
*/