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"
45
#include "drizzled/temporal.h"
52
/** Create a field suitable for create of table. */
53
CreateField::CreateField(Field *old_field, Field *orig_field)
56
field_name= change= old_field->field_name;
57
length= old_field->field_length;
58
flags= old_field->flags;
59
unireg_check= old_field->unireg_check;
60
pack_length= old_field->pack_length();
61
key_length= old_field->key_length();
62
sql_type= old_field->real_type();
63
charset= old_field->charset(); // May be NULL ptr
64
comment= old_field->comment;
65
decimals= old_field->decimals();
67
/* Fix if the original table had 4 byte pointer blobs */
68
if (flags & BLOB_FLAG)
69
pack_length= (pack_length - old_field->table->s->blob_ptr_size + portable_sizeof_char_ptr);
73
case DRIZZLE_TYPE_BLOB:
74
sql_type= DRIZZLE_TYPE_BLOB;
75
length/= charset->mbmaxlen;
76
key_length/= charset->mbmaxlen;
78
case DRIZZLE_TYPE_ENUM:
79
case DRIZZLE_TYPE_VARCHAR:
80
/* This is corrected in create_length_to_internal_length */
81
length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
87
if (flags & (ENUM_FLAG | SET_FLAG))
88
interval= ((Field_enum*) old_field)->typelib;
94
if (!(flags & (NO_DEFAULT_VALUE_FLAG )) &&
95
old_field->ptr && orig_field &&
96
(sql_type != DRIZZLE_TYPE_TIMESTAMP || /* set def only if */
97
old_field->table->timestamp_field != old_field || /* timestamp field */
98
unireg_check == Field::TIMESTAMP_UN_FIELD)) /* has default val */
102
/* Get the value from default_values */
103
diff= (ptrdiff_t) (orig_field->table->s->default_values - orig_field->table->record[0]);
104
orig_field->move_field_offset(diff); // Points now at default_values
105
if (! orig_field->is_real_null())
107
char buff[MAX_FIELD_WIDTH], *pos;
108
String tmp(buff, sizeof(buff), charset), *res;
109
res= orig_field->val_str(&tmp);
110
pos= (char*) sql_strmake(res->ptr(), res->length());
111
def= new Item_string(pos, res->length(), charset);
113
orig_field->move_field_offset(-diff); // Back to record[0]
118
Convert CreateField::length from number of characters to number of bytes.
120
void CreateField::create_length_to_internal_length(void)
124
case DRIZZLE_TYPE_BLOB:
125
case DRIZZLE_TYPE_VARCHAR:
126
length*= charset->mbmaxlen;
128
pack_length= calc_pack_length(sql_type, length);
130
case DRIZZLE_TYPE_ENUM:
131
/* Pack_length already calculated in ::init() */
132
length*= charset->mbmaxlen;
133
key_length= pack_length;
135
case DRIZZLE_TYPE_DECIMAL:
136
key_length= pack_length=
137
my_decimal_get_binary_size(my_decimal_length_to_precision(length,
144
key_length= pack_length= calc_pack_length(sql_type, length);
150
Init for a tmp table field. To be extended if need be.
152
void CreateField::init_for_tmp_table(enum_field_types sql_type_arg,
154
uint32_t decimals_arg,
158
sql_type= sql_type_arg;
159
char_length= length= length_arg;;
160
unireg_check= Field::NONE;
162
charset= &my_charset_bin;
163
decimals= decimals_arg & FIELDFLAG_MAX_DEC;
167
flags= NOT_NULL_FLAG;
172
bool CreateField::init(Session *,
174
enum_field_types fld_type,
177
uint32_t fld_type_modifier,
178
Item *fld_default_value,
179
Item *fld_on_update_value,
180
LEX_STRING *fld_comment,
182
List<String> *fld_interval_list,
183
const CHARSET_INFO * const fld_charset,
185
enum column_format_type column_format_in)
188
uint32_t sign_len= 0;
189
uint32_t allowed_type_modifier= 0;
190
uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
193
field_name= fld_name;
194
def= fld_default_value;
195
flags= fld_type_modifier;
196
flags|= (((uint32_t)column_format_in & COLUMN_FORMAT_MASK) << COLUMN_FORMAT_FLAGS);
197
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
198
Field::NEXT_NUMBER : Field::NONE);
199
decimals= fld_decimals ? (uint32_t)atoi(fld_decimals) : 0;
200
if (decimals >= NOT_FIXED_DEC)
202
my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
211
pack_length= key_length= 0;
212
charset= fld_charset;
213
interval_list.empty();
215
comment= *fld_comment;
218
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
219
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
221
if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
222
(fld_type_modifier & NOT_NULL_FLAG) && fld_type != DRIZZLE_TYPE_TIMESTAMP)
223
flags|= NO_DEFAULT_VALUE_FLAG;
225
if (fld_length && !(length= (uint32_t) atoi(fld_length)))
227
sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
231
case DRIZZLE_TYPE_LONG:
233
length= MAX_INT_WIDTH+sign_len;
234
allowed_type_modifier= AUTO_INCREMENT_FLAG;
236
case DRIZZLE_TYPE_LONGLONG:
238
length= MAX_BIGINT_WIDTH;
239
allowed_type_modifier= AUTO_INCREMENT_FLAG;
241
case DRIZZLE_TYPE_NULL:
243
case DRIZZLE_TYPE_DECIMAL:
244
my_decimal_trim(&length, &decimals);
245
if (length > DECIMAL_MAX_PRECISION)
247
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
248
DECIMAL_MAX_PRECISION);
251
if (length < decimals)
253
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
256
length= my_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
257
pack_length= my_decimal_get_binary_size(length, decimals);
259
case DRIZZLE_TYPE_VARCHAR:
261
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
262
if they don't have a default value
264
max_field_charlength= MAX_FIELD_VARCHARLENGTH;
266
case DRIZZLE_TYPE_BLOB:
267
if (fld_default_value)
269
/* Allow empty as default value. */
271
res= fld_default_value->val_str(&str);
274
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
281
case DRIZZLE_TYPE_DOUBLE:
282
allowed_type_modifier= AUTO_INCREMENT_FLAG;
283
if (!fld_length && !fld_decimals)
286
decimals= NOT_FIXED_DEC;
288
if (length < decimals &&
289
decimals != NOT_FIXED_DEC)
291
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
295
case DRIZZLE_TYPE_TIMESTAMP:
298
length= drizzled::DateTime::MAX_STRING_LENGTH;
301
/* This assert() should be correct due to absence of length
302
specifiers for timestamp. Previous manipulation also wasn't
303
ever called (from examining lcov)
305
assert(length == (uint32_t)drizzled::DateTime::MAX_STRING_LENGTH);
307
flags|= UNSIGNED_FLAG;
308
if (fld_default_value)
310
/* Grammar allows only NOW() value for ON UPDATE clause */
311
if (fld_default_value->type() == Item::FUNC_ITEM &&
312
((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
314
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
315
Field::TIMESTAMP_DN_FIELD);
317
We don't need default value any longer moreover it is dangerous.
318
Everything handled by unireg_check further.
323
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
329
If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
330
or ON UPDATE values then for the sake of compatiblity we should treat
331
this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
332
have another TIMESTAMP column with auto-set option before this one)
333
or DEFAULT 0 (in other cases).
334
So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
335
replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
336
information about all TIMESTAMP fields in table will be availiable.
338
If we have TIMESTAMP NULL column without explicit DEFAULT value
339
we treat it as having DEFAULT NULL attribute.
341
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
342
(flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
346
case DRIZZLE_TYPE_DATE:
347
length= drizzled::Date::MAX_STRING_LENGTH;
349
case DRIZZLE_TYPE_DATETIME:
350
length= drizzled::DateTime::MAX_STRING_LENGTH;
352
case DRIZZLE_TYPE_ENUM:
354
/* Should be safe. */
355
pack_length= get_enum_pack_length(fld_interval_list->elements);
357
List_iterator<String> it(*fld_interval_list);
360
interval_list.push_back(tmp);
365
/* Remember the value of length */
368
if (!(flags & BLOB_FLAG) &&
369
((length > max_field_charlength &&
370
fld_type != DRIZZLE_TYPE_ENUM &&
371
(fld_type != DRIZZLE_TYPE_VARCHAR || fld_default_value)) ||
372
(!length && fld_type != DRIZZLE_TYPE_VARCHAR)))
374
my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ? ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
376
fld_name, max_field_charlength);
379
fld_type_modifier&= AUTO_INCREMENT_FLAG;
380
if ((~allowed_type_modifier) & fld_type_modifier)
382
my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
386
return false; /* success */