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
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/long.h"
41
#include "drizzled/field/int64_t.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/temporal.h"
55
/** Create a field suitable for create of table. */
56
CreateField::CreateField(Field *old_field, Field *orig_field)
59
field_name= change= old_field->field_name;
60
length= old_field->field_length;
61
flags= old_field->flags;
62
unireg_check= old_field->unireg_check;
63
pack_length= old_field->pack_length();
64
key_length= old_field->key_length();
65
sql_type= old_field->real_type();
66
charset= old_field->charset(); // May be NULL ptr
67
comment= old_field->comment;
68
decimals= old_field->decimals();
70
/* Fix if the original table had 4 byte pointer blobs */
71
if (flags & BLOB_FLAG)
72
pack_length= (pack_length - old_field->table->s->blob_ptr_size + portable_sizeof_char_ptr);
76
case DRIZZLE_TYPE_BLOB:
77
sql_type= DRIZZLE_TYPE_BLOB;
78
length/= charset->mbmaxlen;
79
key_length/= charset->mbmaxlen;
81
case DRIZZLE_TYPE_ENUM:
82
case DRIZZLE_TYPE_VARCHAR:
83
/* This is corrected in create_length_to_internal_length */
84
length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
90
if (flags & ENUM_FLAG)
91
interval= ((Field_enum*) old_field)->typelib;
97
if (!(flags & (NO_DEFAULT_VALUE_FLAG )) &&
98
old_field->ptr && orig_field &&
99
(sql_type != DRIZZLE_TYPE_TIMESTAMP || /* set def only if */
100
old_field->table->timestamp_field != old_field || /* timestamp field */
101
unireg_check == Field::TIMESTAMP_UN_FIELD)) /* has default val */
105
/* Get the value from default_values */
106
diff= (ptrdiff_t) (orig_field->table->s->default_values - orig_field->table->record[0]);
107
orig_field->move_field_offset(diff); // Points now at default_values
108
if (! orig_field->is_real_null())
110
char buff[MAX_FIELD_WIDTH], *pos;
111
String tmp(buff, sizeof(buff), charset), *res;
112
res= orig_field->val_str(&tmp);
113
pos= (char*) memory::sql_strmake(res->ptr(), res->length());
114
def= new Item_string(pos, res->length(), charset);
116
orig_field->move_field_offset(-diff); // Back to record[0]
121
Convert CreateField::length from number of characters to number of bytes.
123
void CreateField::create_length_to_internal_length(void)
127
case DRIZZLE_TYPE_BLOB:
128
case DRIZZLE_TYPE_VARCHAR:
129
length*= charset->mbmaxlen;
131
pack_length= calc_pack_length(sql_type, length);
133
case DRIZZLE_TYPE_ENUM:
134
/* Pack_length already calculated in ::init() */
135
length*= charset->mbmaxlen;
136
key_length= pack_length;
138
case DRIZZLE_TYPE_DECIMAL:
139
key_length= pack_length=
140
my_decimal_get_binary_size(my_decimal_length_to_precision(length,
147
key_length= pack_length= calc_pack_length(sql_type, length);
153
Init for a tmp table field. To be extended if need be.
155
void CreateField::init_for_tmp_table(enum_field_types sql_type_arg,
157
uint32_t decimals_arg,
161
sql_type= sql_type_arg;
162
char_length= length= length_arg;;
163
unireg_check= Field::NONE;
165
charset= &my_charset_bin;
166
decimals= decimals_arg & FIELDFLAG_MAX_DEC;
170
flags= NOT_NULL_FLAG;
175
bool CreateField::init(Session *,
177
enum_field_types fld_type,
180
uint32_t fld_type_modifier,
181
Item *fld_default_value,
182
Item *fld_on_update_value,
183
LEX_STRING *fld_comment,
185
List<String> *fld_interval_list,
186
const CHARSET_INFO * const fld_charset,
188
enum column_format_type column_format_in)
191
uint32_t sign_len= 0;
192
uint32_t allowed_type_modifier= 0;
193
uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
196
field_name= fld_name;
197
def= fld_default_value;
198
flags= fld_type_modifier;
199
flags|= (((uint32_t)column_format_in & COLUMN_FORMAT_MASK) << COLUMN_FORMAT_FLAGS);
200
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
201
Field::NEXT_NUMBER : Field::NONE);
202
decimals= fld_decimals ? (uint32_t)atoi(fld_decimals) : 0;
203
if (decimals >= NOT_FIXED_DEC)
205
my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
214
pack_length= key_length= 0;
215
charset= fld_charset;
216
interval_list.empty();
218
comment= *fld_comment;
221
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
222
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
224
if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
225
(fld_type_modifier & NOT_NULL_FLAG) && fld_type != DRIZZLE_TYPE_TIMESTAMP)
226
flags|= NO_DEFAULT_VALUE_FLAG;
228
if (fld_length && !(length= (uint32_t) atoi(fld_length)))
230
sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
234
case DRIZZLE_TYPE_LONG:
236
length= MAX_INT_WIDTH+sign_len;
237
allowed_type_modifier= AUTO_INCREMENT_FLAG;
239
case DRIZZLE_TYPE_LONGLONG:
241
length= MAX_BIGINT_WIDTH;
242
allowed_type_modifier= AUTO_INCREMENT_FLAG;
244
case DRIZZLE_TYPE_NULL:
246
case DRIZZLE_TYPE_DECIMAL:
247
my_decimal_trim(&length, &decimals);
248
if (length > DECIMAL_MAX_PRECISION)
250
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
251
DECIMAL_MAX_PRECISION);
254
if (length < decimals)
256
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
259
length= my_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
260
pack_length= my_decimal_get_binary_size(length, decimals);
262
case DRIZZLE_TYPE_VARCHAR:
264
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
265
if they don't have a default value
267
max_field_charlength= MAX_FIELD_VARCHARLENGTH;
269
case DRIZZLE_TYPE_BLOB:
270
if (fld_default_value)
272
/* Allow empty as default value. */
274
res= fld_default_value->val_str(&str);
277
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
284
case DRIZZLE_TYPE_DOUBLE:
285
allowed_type_modifier= AUTO_INCREMENT_FLAG;
286
if (!fld_length && !fld_decimals)
289
decimals= NOT_FIXED_DEC;
291
if (length < decimals &&
292
decimals != NOT_FIXED_DEC)
294
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
298
case DRIZZLE_TYPE_TIMESTAMP:
301
length= DateTime::MAX_STRING_LENGTH;
304
/* This assert() should be correct due to absence of length
305
specifiers for timestamp. Previous manipulation also wasn't
306
ever called (from examining lcov)
308
assert(length == (uint32_t)DateTime::MAX_STRING_LENGTH);
310
flags|= UNSIGNED_FLAG;
311
if (fld_default_value)
313
/* Grammar allows only NOW() value for ON UPDATE clause */
314
if (fld_default_value->type() == Item::FUNC_ITEM &&
315
((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
317
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
318
Field::TIMESTAMP_DN_FIELD);
320
We don't need default value any longer moreover it is dangerous.
321
Everything handled by unireg_check further.
326
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
332
If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
333
or ON UPDATE values then for the sake of compatiblity we should treat
334
this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
335
have another TIMESTAMP column with auto-set option before this one)
336
or DEFAULT 0 (in other cases).
337
So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
338
replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
339
information about all TIMESTAMP fields in table will be availiable.
341
If we have TIMESTAMP NULL column without explicit DEFAULT value
342
we treat it as having DEFAULT NULL attribute.
344
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
345
(flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
349
case DRIZZLE_TYPE_DATE:
350
length= Date::MAX_STRING_LENGTH;
352
case DRIZZLE_TYPE_DATETIME:
353
length= DateTime::MAX_STRING_LENGTH;
355
case DRIZZLE_TYPE_ENUM:
357
/* Should be safe. */
358
pack_length= get_enum_pack_length(fld_interval_list->elements);
360
List_iterator<String> it(*fld_interval_list);
363
interval_list.push_back(tmp);
368
/* Remember the value of length */
371
if (!(flags & BLOB_FLAG) &&
372
((length > max_field_charlength &&
373
fld_type != DRIZZLE_TYPE_ENUM &&
374
(fld_type != DRIZZLE_TYPE_VARCHAR || fld_default_value)) ||
375
(!length && fld_type != DRIZZLE_TYPE_VARCHAR)))
377
my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ? ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
379
fld_name, max_field_charlength);
382
fld_type_modifier&= AUTO_INCREMENT_FLAG;
383
if ((~allowed_type_modifier) & fld_type_modifier)
385
my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
389
return false; /* success */
392
} /* namespace drizzled */