~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
22
#include <drizzled/server_includes.h>
23
#include <drizzled/field/enum.h>
550 by Monty Taylor
Moved error.h into just the files that need it.
24
#include <drizzled/error.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
25
#include <drizzled/table.h>
26
#include <drizzled/session.h>
438.4.1 by Lee
breaking out enum field classes
27
28
/****************************************************************************
29
** enum type.
30
** This is a string which only can have a selection of different values.
31
** If one uses this string in a number context one gets the type number.
32
****************************************************************************/
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
45
void Field_enum::store_type(uint64_t value)
46
{
47
  switch (packlength) {
481 by Brian Aker
Remove all of uchar.
48
  case 1: ptr[0]= (unsigned char) value;  break;
438.4.1 by Lee
breaking out enum field classes
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
  }
80
}
81
82
83
/**
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
482 by Brian Aker
Remove uint.
89
int Field_enum::store(const char *from, uint32_t length, const CHARSET_INFO * const cs)
438.4.1 by Lee
breaking out enum field classes
90
{
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))
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
98
  {
482 by Brian Aker
Remove uint.
99
    uint32_t dummy_errors;
438.4.1 by Lee
breaking out enum field classes
100
    tmpstr.copy(from, length, cs, field_charset, &dummy_errors);
101
    from= tmpstr.ptr();
102
    length=  tmpstr.length();
103
  }
104
105
  /* Remove end space */
106
  length= field_charset->cset->lengthsp(field_charset, from, length);
482 by Brian Aker
Remove uint.
107
  uint32_t tmp=find_type2(typelib, from, length, field_charset);
438.4.1 by Lee
breaking out enum field classes
108
  if (!tmp)
109
  {
110
    if (length < 6) // Can't be more than 99999 enums
111
    {
112
      /* This is for reading numbers with LOAD DATA INFILE */
113
      char *end;
895 by Brian Aker
Completion (?) of uint conversion.
114
      tmp=(uint32_t) my_strntoul(cs,from,length,10,&end,&err);
438.4.1 by Lee
breaking out enum field classes
115
      if (err || end != from+length || tmp > typelib->count)
116
      {
117
	tmp=0;
118
	set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
119
      }
120
      if (!table->in_use->count_cuted_fields)
121
        err= 0;
122
    }
123
    else
124
      set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
125
  }
126
  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,
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
138
                      bool )
438.4.1 by Lee
breaking out enum field classes
139
{
140
  int error= 0;
141
  if ((uint64_t) nr > typelib->count || nr == 0)
142
  {
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
    }
149
  }
895 by Brian Aker
Completion (?) of uint conversion.
150
  store_type((uint64_t) (uint32_t) nr);
438.4.1 by Lee
breaking out enum field classes
151
  return error;
152
}
153
154
155
double Field_enum::val_real(void)
156
{
157
  return (double) Field_enum::val_int();
158
}
159
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
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
209
   Saves the real type in the first byte and the pack length in the
438.4.1 by Lee
breaking out enum field classes
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
*/
481 by Brian Aker
Remove all of uchar.
217
int Field_enum::do_save_field_metadata(unsigned char *metadata_ptr)
438.4.1 by Lee
breaking out enum field classes
218
{
219
  *metadata_ptr= real_type();
220
  *(metadata_ptr + 1)= pack_length();
221
  return 2;
222
}
223
224
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
225
String *Field_enum::val_str(String *,
438.4.1 by Lee
breaking out enum field classes
226
			    String *val_ptr)
227
{
895 by Brian Aker
Completion (?) of uint conversion.
228
  uint32_t tmp=(uint32_t) Field_enum::val_int();
438.4.1 by Lee
breaking out enum field classes
229
  if (!tmp || tmp > typelib->count)
230
    val_ptr->set("", 0, field_charset);
231
  else
232
    val_ptr->set((const char*) typelib->type_names[tmp-1],
233
		 typelib->type_lengths[tmp-1],
234
		 field_charset);
235
  return val_ptr;
236
}
237
481 by Brian Aker
Remove all of uchar.
238
int Field_enum::cmp(const unsigned char *a_ptr, const unsigned char *b_ptr)
438.4.1 by Lee
breaking out enum field classes
239
{
481 by Brian Aker
Remove all of uchar.
240
  unsigned char *old= ptr;
241
  ptr= (unsigned char*) a_ptr;
438.4.1 by Lee
breaking out enum field classes
242
  uint64_t a=Field_enum::val_int();
481 by Brian Aker
Remove all of uchar.
243
  ptr= (unsigned char*) b_ptr;
438.4.1 by Lee
breaking out enum field classes
244
  uint64_t b=Field_enum::val_int();
245
  ptr= old;
246
  return (a < b) ? -1 : (a > b) ? 1 : 0;
247
}
248
779.1.27 by Monty Taylor
Got rid of __attribute__((unused)) and the like from the .cc files.
249
void Field_enum::sort_string(unsigned char *to,uint32_t )
438.4.1 by Lee
breaking out enum field classes
250
{
251
  uint64_t value=Field_enum::val_int();
252
  to+=packlength-1;
482 by Brian Aker
Remove uint.
253
  for (uint32_t i=0 ; i < packlength ; i++)
438.4.1 by Lee
breaking out enum field classes
254
  {
481 by Brian Aker
Remove all of uchar.
255
    *to-- = (unsigned char) (value & 255);
438.4.1 by Lee
breaking out enum field classes
256
    value>>=8;
257
  }
258
}
259
260
261
void Field_enum::sql_type(String &res) const
262
{
263
  char buffer[255];
264
  String enum_item(buffer, sizeof(buffer), res.charset());
265
266
  res.length(0);
267
  res.append(STRING_WITH_LEN("enum("));
268
269
  bool flag=0;
482 by Brian Aker
Remove uint.
270
  uint32_t *len= typelib->type_lengths;
438.4.1 by Lee
breaking out enum field classes
271
  for (const char **pos= typelib->type_names; *pos; pos++, len++)
272
  {
482 by Brian Aker
Remove uint.
273
    uint32_t dummy_errors;
438.4.1 by Lee
breaking out enum field classes
274
    if (flag)
275
      res.append(',');
276
    /* convert to res.charset() == utf8, then quote */
277
    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"
278
    append_unescaped(&res, enum_item.c_ptr(), enum_item.length());
438.4.1 by Lee
breaking out enum field classes
279
    flag= 1;
280
  }
281
  res.append(')');
282
}
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
}