~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/enum.cc

  • Committer: Jay Pipes
  • Date: 2009-03-16 15:20:27 UTC
  • mto: (934.3.7 mordred)
  • mto: This revision was merged to the branch mainline in revision 938.
  • Revision ID: jpipes@serialcoder-20090316152027-njlreaim8vxqta6c
Fixes ENUM field type to throw an error on bad data input.  0 is now not
allowed on insertion.  MySQL allows 0, in the manual it states 0 is "the
null string error index" whatever that means.  Drizzle doesn't allow it.

Corrected test cases.

Also cleans up indentation on JOIN::exec() which was bothering me.

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 */
20
20
 
21
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>
 
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);
95
 
 
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
 
  }
 
93
  uint32_t tmp;
104
94
 
105
95
  /* Remove end space */
106
96
  length= field_charset->cset->lengthsp(field_charset, from, length);
107
 
  uint32_t tmp=find_type2(typelib, from, length, field_charset);
108
 
  if (!tmp)
 
97
  tmp= find_type2(typelib, from, length, field_charset);
 
98
  if (! tmp)
109
99
  {
110
 
    if (length < 6) // Can't be more than 99999 enums
 
100
    if (length < 6) /* Can't be more than 99999 enums */
111
101
    {
112
102
      /* This is for reading numbers with LOAD DATA INFILE */
113
 
      char *end;
114
 
      tmp=(uint32_t) my_strntoul(cs,from,length,10,&end,&err);
115
 
      if (err || end != from+length || tmp > typelib->count)
 
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)
116
109
      {
117
 
        tmp=0;
118
 
        set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
110
        my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
 
111
        return 1;
119
112
      }
120
 
      if (!table->in_use->count_cuted_fields)
121
 
        err= 0;
122
113
    }
123
114
    else
124
 
      set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
 
115
    {
 
116
      my_error(ER_INVALID_ENUM_VALUE, MYF(ME_FATALERROR), from);
 
117
      return 1;
 
118
    }
125
119
  }
126
120
  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 )
139
 
{
140
 
  int error= 0;
141
 
  if ((uint64_t) nr > typelib->count || nr == 0)
 
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)
142
139
  {
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
 
    }
 
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;
149
147
  }
150
 
  store_type((uint64_t) (uint32_t) nr);
151
 
  return error;
 
148
  store_type((uint64_t) (uint32_t) from);
 
149
  return 0;
152
150
}
153
151
 
154
 
 
155
152
double Field_enum::val_real(void)
156
153
{
157
154
  return (double) Field_enum::val_int();
158
155
}
159
156
 
160
 
 
161
157
int64_t Field_enum::val_int(void)
162
158
{
163
159
  switch (packlength) {
202
198
  return 0;                                     // impossible
203
199
}
204
200
 
205
 
 
206
201
/**
207
202
   Save the field metadata for enum fields.
208
203
 
221
216
  return 2;
222
217
}
223
218
 
224
 
 
225
 
String *Field_enum::val_str(String *,
226
 
                            String *val_ptr)
 
219
String *Field_enum::val_str(String *, String *val_ptr)
227
220
{
228
221
  uint32_t tmp=(uint32_t) Field_enum::val_int();
229
222
  if (!tmp || tmp > typelib->count)
257
250
  }
258
251
}
259
252
 
260
 
 
261
253
void Field_enum::sql_type(String &res) const
262
254
{
263
255
  char buffer[255];
281
273
  res.append(')');
282
274
}
283
275
 
284
 
 
285
276
Field *Field_enum::new_field(MEM_ROOT *root, Table *new_table,
286
277
                             bool keep_type)
287
278
{