1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008-2009 Sun Microsystems
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; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
* @file Implementation of CreateField class
24
#include "drizzled/server_includes.h"
26
#include "drizzled/sql_select.h"
27
#include "drizzled/error.h"
28
#include "drizzled/field.h"
29
#include "drizzled/create_field.h"
30
#include "drizzled/field/str.h"
31
#include "drizzled/field/num.h"
32
#include "drizzled/field/blob.h"
33
#include "drizzled/field/enum.h"
34
#include "drizzled/field/null.h"
35
#include "drizzled/field/date.h"
36
#include "drizzled/field/decimal.h"
37
#include "drizzled/field/real.h"
38
#include "drizzled/field/double.h"
39
#include "drizzled/field/long.h"
40
#include "drizzled/field/int64_t.h"
41
#include "drizzled/field/num.h"
42
#include "drizzled/field/timestamp.h"
43
#include "drizzled/field/datetime.h"
44
#include "drizzled/field/varstring.h"
46
/** Create a field suitable for create of table. */
47
CreateField::CreateField(Field *old_field, Field *orig_field)
50
field_name= change= old_field->field_name;
51
length= old_field->field_length;
52
flags= old_field->flags;
53
unireg_check= old_field->unireg_check;
54
pack_length= old_field->pack_length();
55
key_length= old_field->key_length();
56
sql_type= old_field->real_type();
57
charset= old_field->charset(); // May be NULL ptr
58
comment= old_field->comment;
59
decimals= old_field->decimals();
61
/* Fix if the original table had 4 byte pointer blobs */
62
if (flags & BLOB_FLAG)
63
pack_length= (pack_length - old_field->table->s->blob_ptr_size + portable_sizeof_char_ptr);
67
case DRIZZLE_TYPE_BLOB:
68
sql_type= DRIZZLE_TYPE_BLOB;
69
length/= charset->mbmaxlen;
70
key_length/= charset->mbmaxlen;
72
case DRIZZLE_TYPE_ENUM:
73
case DRIZZLE_TYPE_VARCHAR:
74
/* This is corrected in create_length_to_internal_length */
75
length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
81
if (flags & (ENUM_FLAG | SET_FLAG))
82
interval= ((Field_enum*) old_field)->typelib;
88
if (!(flags & (NO_DEFAULT_VALUE_FLAG )) &&
89
old_field->ptr && orig_field &&
90
(sql_type != DRIZZLE_TYPE_TIMESTAMP || /* set def only if */
91
old_field->table->timestamp_field != old_field || /* timestamp field */
92
unireg_check == Field::TIMESTAMP_UN_FIELD)) /* has default val */
96
/* Get the value from default_values */
97
diff= (ptrdiff_t) (orig_field->table->s->default_values - orig_field->table->record[0]);
98
orig_field->move_field_offset(diff); // Points now at default_values
99
if (! orig_field->is_real_null())
101
char buff[MAX_FIELD_WIDTH], *pos;
102
String tmp(buff, sizeof(buff), charset), *res;
103
res= orig_field->val_str(&tmp);
104
pos= (char*) sql_strmake(res->ptr(), res->length());
105
def= new Item_string(pos, res->length(), charset);
107
orig_field->move_field_offset(-diff); // Back to record[0]
112
Convert CreateField::length from number of characters to number of bytes.
114
void CreateField::create_length_to_internal_length(void)
118
case DRIZZLE_TYPE_BLOB:
119
case DRIZZLE_TYPE_VARCHAR:
120
length*= charset->mbmaxlen;
122
pack_length= calc_pack_length(sql_type, length);
124
case DRIZZLE_TYPE_ENUM:
125
/* Pack_length already calculated in ::init() */
126
length*= charset->mbmaxlen;
127
key_length= pack_length;
129
case DRIZZLE_TYPE_NEWDECIMAL:
130
key_length= pack_length=
131
my_decimal_get_binary_size(my_decimal_length_to_precision(length,
138
key_length= pack_length= calc_pack_length(sql_type, length);
144
Init for a tmp table field. To be extended if need be.
146
void CreateField::init_for_tmp_table(enum_field_types sql_type_arg,
147
uint32_t length_arg, uint32_t decimals_arg,
148
bool maybe_null, bool is_unsigned)
151
sql_type= sql_type_arg;
152
char_length= length= length_arg;;
153
unireg_check= Field::NONE;
155
charset= &my_charset_bin;
156
pack_flag= (FIELDFLAG_NUMBER |
157
((decimals_arg & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT) |
158
(maybe_null ? FIELDFLAG_MAYBE_NULL : 0) |
159
(is_unsigned ? 0 : FIELDFLAG_DECIMAL));
162
bool CreateField::init(Session *,
164
enum_field_types fld_type,
167
uint32_t fld_type_modifier,
168
Item *fld_default_value,
169
Item *fld_on_update_value,
170
LEX_STRING *fld_comment,
172
List<String> *fld_interval_list,
173
const CHARSET_INFO * const fld_charset,
175
enum column_format_type column_format_in)
178
uint32_t sign_len= 0;
179
uint32_t allowed_type_modifier= 0;
180
uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
183
field_name= fld_name;
184
def= fld_default_value;
185
flags= fld_type_modifier;
186
flags|= (((uint32_t)column_format_in & COLUMN_FORMAT_MASK) << COLUMN_FORMAT_FLAGS);
187
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
188
Field::NEXT_NUMBER : Field::NONE);
189
decimals= fld_decimals ? (uint32_t)atoi(fld_decimals) : 0;
190
if (decimals >= NOT_FIXED_DEC)
192
my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
201
pack_length= key_length= 0;
202
charset= fld_charset;
203
interval_list.empty();
205
comment= *fld_comment;
208
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
209
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
211
if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
212
(fld_type_modifier & NOT_NULL_FLAG) && fld_type != DRIZZLE_TYPE_TIMESTAMP)
213
flags|= NO_DEFAULT_VALUE_FLAG;
215
if (fld_length && !(length= (uint32_t) atoi(fld_length)))
216
fld_length= 0; /* purecov: inspected */
217
sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
221
case DRIZZLE_TYPE_TINY:
223
length= MAX_TINYINT_WIDTH+sign_len;
224
allowed_type_modifier= AUTO_INCREMENT_FLAG;
226
case DRIZZLE_TYPE_LONG:
228
length= MAX_INT_WIDTH+sign_len;
229
allowed_type_modifier= AUTO_INCREMENT_FLAG;
231
case DRIZZLE_TYPE_LONGLONG:
233
length= MAX_BIGINT_WIDTH;
234
allowed_type_modifier= AUTO_INCREMENT_FLAG;
236
case DRIZZLE_TYPE_NULL:
238
case DRIZZLE_TYPE_NEWDECIMAL:
239
my_decimal_trim(&length, &decimals);
240
if (length > DECIMAL_MAX_PRECISION)
242
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
243
DECIMAL_MAX_PRECISION);
246
if (length < decimals)
248
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
251
length= my_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
252
pack_length= my_decimal_get_binary_size(length, decimals);
254
case DRIZZLE_TYPE_VARCHAR:
256
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
257
if they don't have a default value
259
max_field_charlength= MAX_FIELD_VARCHARLENGTH;
261
case DRIZZLE_TYPE_BLOB:
262
if (fld_default_value)
264
/* Allow empty as default value. */
266
res= fld_default_value->val_str(&str);
269
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
276
case DRIZZLE_TYPE_DOUBLE:
277
allowed_type_modifier= AUTO_INCREMENT_FLAG;
278
if (!fld_length && !fld_decimals)
281
decimals= NOT_FIXED_DEC;
283
if (length < decimals &&
284
decimals != NOT_FIXED_DEC)
286
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
290
case DRIZZLE_TYPE_TIMESTAMP:
293
/* Compressed date YYYYMMDDHHMMSS */
294
length= MAX_DATETIME_COMPRESSED_WIDTH;
296
else if (length != MAX_DATETIME_WIDTH)
299
We support only even TIMESTAMP lengths less or equal than 14
300
and 19 as length of 4.1 compatible representation.
302
length= ((length+1)/2)*2; /* purecov: inspected */
303
length= cmin(length, (uint32_t)MAX_DATETIME_COMPRESSED_WIDTH); /* purecov: inspected */
305
flags|= UNSIGNED_FLAG;
306
if (fld_default_value)
308
/* Grammar allows only NOW() value for ON UPDATE clause */
309
if (fld_default_value->type() == Item::FUNC_ITEM &&
310
((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
312
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
313
Field::TIMESTAMP_DN_FIELD);
315
We don't need default value any longer moreover it is dangerous.
316
Everything handled by unireg_check further.
321
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
327
If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
328
or ON UPDATE values then for the sake of compatiblity we should treat
329
this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
330
have another TIMESTAMP column with auto-set option before this one)
331
or DEFAULT 0 (in other cases).
332
So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
333
replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
334
information about all TIMESTAMP fields in table will be availiable.
336
If we have TIMESTAMP NULL column without explicit DEFAULT value
337
we treat it as having DEFAULT NULL attribute.
339
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
340
(flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
344
case DRIZZLE_TYPE_DATE:
347
case DRIZZLE_TYPE_DATETIME:
348
length= MAX_DATETIME_WIDTH;
350
case DRIZZLE_TYPE_ENUM:
352
/* Should be safe. */
353
pack_length= get_enum_pack_length(fld_interval_list->elements);
355
List_iterator<String> it(*fld_interval_list);
358
interval_list.push_back(tmp);
363
/* Remember the value of length */
366
if (!(flags & BLOB_FLAG) &&
367
((length > max_field_charlength &&
368
fld_type != DRIZZLE_TYPE_ENUM &&
369
(fld_type != DRIZZLE_TYPE_VARCHAR || fld_default_value)) ||
370
(!length && fld_type != DRIZZLE_TYPE_VARCHAR)))
372
my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ? ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
374
fld_name, max_field_charlength); /* purecov: inspected */
377
fld_type_modifier&= AUTO_INCREMENT_FLAG;
378
if ((~allowed_type_modifier) & fld_type_modifier)
380
my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
384
return false; /* success */