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, Inc.
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
27
#include "drizzled/sql_select.h"
28
#include "drizzled/error.h"
29
#include "drizzled/field.h"
30
#include "drizzled/create_field.h"
31
#include "drizzled/field/str.h"
32
#include "drizzled/field/num.h"
33
#include "drizzled/field/blob.h"
34
#include "drizzled/field/enum.h"
35
#include "drizzled/field/null.h"
36
#include "drizzled/field/date.h"
37
#include "drizzled/field/decimal.h"
38
#include "drizzled/field/real.h"
39
#include "drizzled/field/double.h"
40
#include "drizzled/field/int32.h"
41
#include "drizzled/field/int64.h"
42
#include "drizzled/field/num.h"
43
#include "drizzled/field/timestamp.h"
44
#include "drizzled/field/datetime.h"
45
#include "drizzled/field/varstring.h"
46
#include "drizzled/field/uuid.h"
47
#include "drizzled/temporal.h"
48
#include "drizzled/item/string.h"
57
/** Create a field suitable for create of table. */
58
CreateField::CreateField(Field *old_field, Field *orig_field)
61
field_name= change= old_field->field_name;
62
length= old_field->field_length;
63
flags= old_field->flags;
64
unireg_check= old_field->unireg_check;
65
pack_length= old_field->pack_length();
66
key_length= old_field->key_length();
67
sql_type= old_field->real_type();
68
charset= old_field->charset(); // May be NULL ptr
69
comment= old_field->comment;
70
decimals= old_field->decimals();
72
/* Fix if the original table had 4 byte pointer blobs */
73
if (flags & BLOB_FLAG)
74
pack_length= (pack_length - old_field->getTable()->getShare()->blob_ptr_size + portable_sizeof_char_ptr);
78
case DRIZZLE_TYPE_BLOB:
79
sql_type= DRIZZLE_TYPE_BLOB;
80
length/= charset->mbmaxlen;
81
key_length/= charset->mbmaxlen;
83
case DRIZZLE_TYPE_ENUM:
84
case DRIZZLE_TYPE_VARCHAR:
85
/* This is corrected in create_length_to_internal_length */
86
length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
92
if (flags & ENUM_FLAG)
93
interval= ((Field_enum*) old_field)->typelib;
99
if (!(flags & (NO_DEFAULT_VALUE_FLAG)) &&
100
!(flags & AUTO_INCREMENT_FLAG) &&
101
old_field->ptr && orig_field &&
102
(sql_type != DRIZZLE_TYPE_TIMESTAMP || /* set def only if */
103
old_field->getTable()->timestamp_field != old_field || /* timestamp field */
104
unireg_check == Field::TIMESTAMP_UN_FIELD)) /* has default val */
108
/* Get the value from default_values */
109
diff= (ptrdiff_t) (orig_field->getTable()->getDefaultValues() - orig_field->getTable()->getInsertRecord());
110
orig_field->move_field_offset(diff); // Points now at default_values
111
if (! orig_field->is_real_null())
113
char buff[MAX_FIELD_WIDTH], *pos;
114
String tmp(buff, sizeof(buff), charset), *res;
115
res= orig_field->val_str_internal(&tmp);
116
pos= (char*) memory::sql_strmake(res->ptr(), res->length());
117
def= new Item_string(pos, res->length(), charset);
119
orig_field->move_field_offset(-diff); // Back to getInsertRecord()
124
Convert CreateField::length from number of characters to number of bytes.
126
void CreateField::create_length_to_internal_length(void)
130
case DRIZZLE_TYPE_BLOB:
131
case DRIZZLE_TYPE_VARCHAR:
132
length*= charset->mbmaxlen;
134
pack_length= calc_pack_length(sql_type, length);
136
case DRIZZLE_TYPE_ENUM:
137
/* Pack_length already calculated in ::init() */
138
length*= charset->mbmaxlen;
139
key_length= pack_length;
141
case DRIZZLE_TYPE_DECIMAL:
142
key_length= pack_length=
143
my_decimal_get_binary_size(my_decimal_length_to_precision(length,
150
key_length= pack_length= calc_pack_length(sql_type, length);
156
Init for a tmp table field. To be extended if need be.
158
void CreateField::init_for_tmp_table(enum_field_types sql_type_arg,
160
uint32_t decimals_arg,
164
sql_type= sql_type_arg;
165
char_length= length= length_arg;;
166
unireg_check= Field::NONE;
168
charset= &my_charset_bin;
169
decimals= decimals_arg & FIELDFLAG_MAX_DEC;
172
flags= NOT_NULL_FLAG;
177
bool CreateField::init(Session *,
179
enum_field_types fld_type,
182
uint32_t fld_type_modifier,
183
Item *fld_default_value,
184
Item *fld_on_update_value,
185
LEX_STRING *fld_comment,
187
List<String> *fld_interval_list,
188
const CHARSET_INFO * const fld_charset,
190
enum column_format_type column_format_in)
193
uint32_t sign_len= 0;
194
uint32_t allowed_type_modifier= 0;
195
uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
198
field_name= fld_name;
199
def= fld_default_value;
200
flags= fld_type_modifier;
201
flags|= (((uint32_t)column_format_in & COLUMN_FORMAT_MASK) << COLUMN_FORMAT_FLAGS);
202
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
203
Field::NEXT_NUMBER : Field::NONE);
204
decimals= fld_decimals ? (uint32_t)atoi(fld_decimals) : 0;
205
if (decimals >= NOT_FIXED_DEC)
207
my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
216
pack_length= key_length= 0;
217
charset= fld_charset;
218
interval_list.empty();
220
comment= *fld_comment;
223
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
224
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
226
if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
227
(fld_type_modifier & NOT_NULL_FLAG) && fld_type != DRIZZLE_TYPE_TIMESTAMP)
228
flags|= NO_DEFAULT_VALUE_FLAG;
230
if (fld_length && !(length= (uint32_t) atoi(fld_length)))
232
sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
236
case DRIZZLE_TYPE_LONG:
238
length= MAX_INT_WIDTH+sign_len;
239
allowed_type_modifier= AUTO_INCREMENT_FLAG;
241
case DRIZZLE_TYPE_LONGLONG:
243
length= MAX_BIGINT_WIDTH;
244
allowed_type_modifier= AUTO_INCREMENT_FLAG;
246
case DRIZZLE_TYPE_NULL:
248
case DRIZZLE_TYPE_DECIMAL:
249
my_decimal_trim(&length, &decimals);
250
if (length > DECIMAL_MAX_PRECISION)
252
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
253
DECIMAL_MAX_PRECISION);
256
if (length < decimals)
258
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
261
length= my_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
262
pack_length= my_decimal_get_binary_size(length, decimals);
264
case DRIZZLE_TYPE_VARCHAR:
266
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
267
if they don't have a default value
269
max_field_charlength= MAX_FIELD_VARCHARLENGTH;
271
case DRIZZLE_TYPE_BLOB:
272
if (fld_default_value)
274
/* Allow empty as default value. */
276
res= fld_default_value->val_str(&str);
279
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
286
case DRIZZLE_TYPE_DOUBLE:
287
allowed_type_modifier= AUTO_INCREMENT_FLAG;
288
if (!fld_length && !fld_decimals)
291
decimals= NOT_FIXED_DEC;
293
if (length < decimals &&
294
decimals != NOT_FIXED_DEC)
296
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
300
case DRIZZLE_TYPE_TIMESTAMP:
303
length= DateTime::MAX_STRING_LENGTH;
306
/* This assert() should be correct due to absence of length
307
specifiers for timestamp. Previous manipulation also wasn't
308
ever called (from examining lcov)
310
assert(length == (uint32_t)DateTime::MAX_STRING_LENGTH);
312
flags|= UNSIGNED_FLAG;
313
if (fld_default_value)
315
/* Grammar allows only NOW() value for ON UPDATE clause */
316
if (fld_default_value->type() == Item::FUNC_ITEM &&
317
((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
319
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
320
Field::TIMESTAMP_DN_FIELD);
322
We don't need default value any longer moreover it is dangerous.
323
Everything handled by unireg_check further.
328
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
334
If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
335
or ON UPDATE values then for the sake of compatiblity we should treat
336
this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
337
have another TIMESTAMP column with auto-set option before this one)
338
or DEFAULT 0 (in other cases).
339
So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
340
replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
341
information about all TIMESTAMP fields in table will be availiable.
343
If we have TIMESTAMP NULL column without explicit DEFAULT value
344
we treat it as having DEFAULT NULL attribute.
346
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
347
(flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
351
case DRIZZLE_TYPE_DATE:
352
length= Date::MAX_STRING_LENGTH;
354
case DRIZZLE_TYPE_UUID:
355
length= field::Uuid::max_string_length();
357
case DRIZZLE_TYPE_DATETIME:
358
length= DateTime::MAX_STRING_LENGTH;
360
case DRIZZLE_TYPE_ENUM:
362
/* Should be safe. */
365
List_iterator<String> it(*fld_interval_list);
368
interval_list.push_back(tmp);
373
/* Remember the value of length */
376
if (!(flags & BLOB_FLAG) &&
377
((length > max_field_charlength &&
378
fld_type != DRIZZLE_TYPE_ENUM &&
379
(fld_type != DRIZZLE_TYPE_VARCHAR || fld_default_value)) ||
380
(!length && fld_type != DRIZZLE_TYPE_VARCHAR)))
382
my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ? ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
384
fld_name, max_field_charlength);
387
fld_type_modifier&= AUTO_INCREMENT_FLAG;
388
if ((~allowed_type_modifier) & fld_type_modifier)
390
my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
394
return false; /* success */
397
} /* namespace drizzled */