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"
50
using namespace drizzled;
54
/** Create a field suitable for create of table. */
55
CreateField::CreateField(Field *old_field, Field *orig_field)
58
field_name= change= old_field->field_name;
59
length= old_field->field_length;
60
flags= old_field->flags;
61
unireg_check= old_field->unireg_check;
62
pack_length= old_field->pack_length();
63
key_length= old_field->key_length();
64
sql_type= old_field->real_type();
65
charset= old_field->charset(); // May be NULL ptr
66
comment= old_field->comment;
67
decimals= old_field->decimals();
69
/* Fix if the original table had 4 byte pointer blobs */
70
if (flags & BLOB_FLAG)
71
pack_length= (pack_length - old_field->table->s->blob_ptr_size + portable_sizeof_char_ptr);
75
case DRIZZLE_TYPE_BLOB:
76
sql_type= DRIZZLE_TYPE_BLOB;
77
length/= charset->mbmaxlen;
78
key_length/= charset->mbmaxlen;
80
case DRIZZLE_TYPE_ENUM:
81
case DRIZZLE_TYPE_VARCHAR:
82
/* This is corrected in create_length_to_internal_length */
83
length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
89
if (flags & (ENUM_FLAG | SET_FLAG))
90
interval= ((Field_enum*) old_field)->typelib;
96
if (!(flags & (NO_DEFAULT_VALUE_FLAG )) &&
97
old_field->ptr && orig_field &&
98
(sql_type != DRIZZLE_TYPE_TIMESTAMP || /* set def only if */
99
old_field->table->timestamp_field != old_field || /* timestamp field */
100
unireg_check == Field::TIMESTAMP_UN_FIELD)) /* has default val */
104
/* Get the value from default_values */
105
diff= (ptrdiff_t) (orig_field->table->s->default_values - orig_field->table->record[0]);
106
orig_field->move_field_offset(diff); // Points now at default_values
107
if (! orig_field->is_real_null())
109
char buff[MAX_FIELD_WIDTH], *pos;
110
String tmp(buff, sizeof(buff), charset), *res;
111
res= orig_field->val_str(&tmp);
112
pos= (char*) memory::sql_strmake(res->ptr(), res->length());
113
def= new Item_string(pos, res->length(), charset);
115
orig_field->move_field_offset(-diff); // Back to record[0]
120
Convert CreateField::length from number of characters to number of bytes.
122
void CreateField::create_length_to_internal_length(void)
126
case DRIZZLE_TYPE_BLOB:
127
case DRIZZLE_TYPE_VARCHAR:
128
length*= charset->mbmaxlen;
130
pack_length= calc_pack_length(sql_type, length);
132
case DRIZZLE_TYPE_ENUM:
133
/* Pack_length already calculated in ::init() */
134
length*= charset->mbmaxlen;
135
key_length= pack_length;
137
case DRIZZLE_TYPE_DECIMAL:
138
key_length= pack_length=
139
my_decimal_get_binary_size(my_decimal_length_to_precision(length,
146
key_length= pack_length= calc_pack_length(sql_type, length);
152
Init for a tmp table field. To be extended if need be.
154
void CreateField::init_for_tmp_table(enum_field_types sql_type_arg,
156
uint32_t decimals_arg,
160
sql_type= sql_type_arg;
161
char_length= length= length_arg;;
162
unireg_check= Field::NONE;
164
charset= &my_charset_bin;
165
decimals= decimals_arg & FIELDFLAG_MAX_DEC;
169
flags= NOT_NULL_FLAG;
174
bool CreateField::init(Session *,
176
enum_field_types fld_type,
179
uint32_t fld_type_modifier,
180
Item *fld_default_value,
181
Item *fld_on_update_value,
182
LEX_STRING *fld_comment,
184
List<String> *fld_interval_list,
185
const CHARSET_INFO * const fld_charset,
187
enum column_format_type column_format_in)
190
uint32_t sign_len= 0;
191
uint32_t allowed_type_modifier= 0;
192
uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
195
field_name= fld_name;
196
def= fld_default_value;
197
flags= fld_type_modifier;
198
flags|= (((uint32_t)column_format_in & COLUMN_FORMAT_MASK) << COLUMN_FORMAT_FLAGS);
199
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
200
Field::NEXT_NUMBER : Field::NONE);
201
decimals= fld_decimals ? (uint32_t)atoi(fld_decimals) : 0;
202
if (decimals >= NOT_FIXED_DEC)
204
my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
213
pack_length= key_length= 0;
214
charset= fld_charset;
215
interval_list.empty();
217
comment= *fld_comment;
220
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
221
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
223
if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
224
(fld_type_modifier & NOT_NULL_FLAG) && fld_type != DRIZZLE_TYPE_TIMESTAMP)
225
flags|= NO_DEFAULT_VALUE_FLAG;
227
if (fld_length && !(length= (uint32_t) atoi(fld_length)))
229
sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
233
case DRIZZLE_TYPE_LONG:
235
length= MAX_INT_WIDTH+sign_len;
236
allowed_type_modifier= AUTO_INCREMENT_FLAG;
238
case DRIZZLE_TYPE_LONGLONG:
240
length= MAX_BIGINT_WIDTH;
241
allowed_type_modifier= AUTO_INCREMENT_FLAG;
243
case DRIZZLE_TYPE_NULL:
245
case DRIZZLE_TYPE_DECIMAL:
246
my_decimal_trim(&length, &decimals);
247
if (length > DECIMAL_MAX_PRECISION)
249
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
250
DECIMAL_MAX_PRECISION);
253
if (length < decimals)
255
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
258
length= my_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
259
pack_length= my_decimal_get_binary_size(length, decimals);
261
case DRIZZLE_TYPE_VARCHAR:
263
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
264
if they don't have a default value
266
max_field_charlength= MAX_FIELD_VARCHARLENGTH;
268
case DRIZZLE_TYPE_BLOB:
269
if (fld_default_value)
271
/* Allow empty as default value. */
273
res= fld_default_value->val_str(&str);
276
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
283
case DRIZZLE_TYPE_DOUBLE:
284
allowed_type_modifier= AUTO_INCREMENT_FLAG;
285
if (!fld_length && !fld_decimals)
288
decimals= NOT_FIXED_DEC;
290
if (length < decimals &&
291
decimals != NOT_FIXED_DEC)
293
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
297
case DRIZZLE_TYPE_TIMESTAMP:
300
length= drizzled::DateTime::MAX_STRING_LENGTH;
303
/* This assert() should be correct due to absence of length
304
specifiers for timestamp. Previous manipulation also wasn't
305
ever called (from examining lcov)
307
assert(length == (uint32_t)drizzled::DateTime::MAX_STRING_LENGTH);
309
flags|= UNSIGNED_FLAG;
310
if (fld_default_value)
312
/* Grammar allows only NOW() value for ON UPDATE clause */
313
if (fld_default_value->type() == Item::FUNC_ITEM &&
314
((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
316
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
317
Field::TIMESTAMP_DN_FIELD);
319
We don't need default value any longer moreover it is dangerous.
320
Everything handled by unireg_check further.
325
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
331
If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
332
or ON UPDATE values then for the sake of compatiblity we should treat
333
this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
334
have another TIMESTAMP column with auto-set option before this one)
335
or DEFAULT 0 (in other cases).
336
So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
337
replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
338
information about all TIMESTAMP fields in table will be availiable.
340
If we have TIMESTAMP NULL column without explicit DEFAULT value
341
we treat it as having DEFAULT NULL attribute.
343
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
344
(flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
348
case DRIZZLE_TYPE_DATE:
349
length= drizzled::Date::MAX_STRING_LENGTH;
351
case DRIZZLE_TYPE_DATETIME:
352
length= drizzled::DateTime::MAX_STRING_LENGTH;
354
case DRIZZLE_TYPE_ENUM:
356
/* Should be safe. */
357
pack_length= get_enum_pack_length(fld_interval_list->elements);
359
List_iterator<String> it(*fld_interval_list);
362
interval_list.push_back(tmp);
367
/* Remember the value of length */
370
if (!(flags & BLOB_FLAG) &&
371
((length > max_field_charlength &&
372
fld_type != DRIZZLE_TYPE_ENUM &&
373
(fld_type != DRIZZLE_TYPE_VARCHAR || fld_default_value)) ||
374
(!length && fld_type != DRIZZLE_TYPE_VARCHAR)))
376
my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ? ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
378
fld_name, max_field_charlength);
381
fld_type_modifier&= AUTO_INCREMENT_FLAG;
382
if ((~allowed_type_modifier) & fld_type_modifier)
384
my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
388
return false; /* success */