~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/create_field.cc

mergeĀ fromĀ lp

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2008-2009 Sun Microsystems
 
5
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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
 
18
 */
 
19
 
 
20
/**
 
21
 * @file Implementation of CreateField class
 
22
 */
 
23
 
 
24
#include "drizzled/server_includes.h"
 
25
#include <errno.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
 
 
46
/** Create a field suitable for create of table. */
 
47
CreateField::CreateField(Field *old_field, Field *orig_field)
 
48
{
 
49
  field= old_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();
 
60
 
 
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);
 
64
 
 
65
  switch (sql_type) 
 
66
  {
 
67
    case DRIZZLE_TYPE_BLOB:
 
68
      sql_type= DRIZZLE_TYPE_BLOB;
 
69
      length/= charset->mbmaxlen;
 
70
      key_length/= charset->mbmaxlen;
 
71
      break;
 
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;
 
76
      break;
 
77
    default:
 
78
      break;
 
79
  }
 
80
 
 
81
  if (flags & (ENUM_FLAG | SET_FLAG))
 
82
    interval= ((Field_enum*) old_field)->typelib;
 
83
  else
 
84
    interval= 0;
 
85
  def= 0;
 
86
  char_length= length;
 
87
 
 
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 */
 
93
  {
 
94
    ptrdiff_t diff;
 
95
 
 
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())
 
100
    {
 
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);
 
106
    }
 
107
    orig_field->move_field_offset(-diff);       // Back to record[0]
 
108
  }
 
109
}
 
110
 
 
111
/**
 
112
  Convert CreateField::length from number of characters to number of bytes.
 
113
*/
 
114
void CreateField::create_length_to_internal_length(void)
 
115
{
 
116
  switch (sql_type) 
 
117
  {
 
118
    case DRIZZLE_TYPE_BLOB:
 
119
    case DRIZZLE_TYPE_VARCHAR:
 
120
      length*= charset->mbmaxlen;
 
121
      key_length= length;
 
122
      pack_length= calc_pack_length(sql_type, length);
 
123
      break;
 
124
    case DRIZZLE_TYPE_ENUM:
 
125
      /* Pack_length already calculated in ::init() */
 
126
      length*= charset->mbmaxlen;
 
127
      key_length= pack_length;
 
128
      break;
 
129
    case DRIZZLE_TYPE_NEWDECIMAL:
 
130
      key_length= pack_length=
 
131
        my_decimal_get_binary_size(my_decimal_length_to_precision(length,
 
132
                  decimals,
 
133
                  flags &
 
134
                  UNSIGNED_FLAG),
 
135
          decimals);
 
136
      break;
 
137
    default:
 
138
      key_length= pack_length= calc_pack_length(sql_type, length);
 
139
      break;
 
140
  }
 
141
}
 
142
 
 
143
/**
 
144
  Init for a tmp table field. To be extended if need be.
 
145
*/
 
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)
 
149
{
 
150
  field_name= "";
 
151
  sql_type= sql_type_arg;
 
152
  char_length= length= length_arg;;
 
153
  unireg_check= Field::NONE;
 
154
  interval= 0;
 
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));
 
160
}
 
161
 
 
162
bool CreateField::init(Session *,
 
163
                        char *fld_name,
 
164
                        enum_field_types fld_type,
 
165
                        char *fld_length,
 
166
                        char *fld_decimals,
 
167
                        uint32_t fld_type_modifier,
 
168
                        Item *fld_default_value,
 
169
                        Item *fld_on_update_value,
 
170
                        LEX_STRING *fld_comment,
 
171
                        char *fld_change,
 
172
                        List<String> *fld_interval_list,
 
173
                        const CHARSET_INFO * const fld_charset,
 
174
                        uint32_t,
 
175
                        enum column_format_type column_format_in)
 
176
                        
 
177
{
 
178
  uint32_t sign_len= 0;
 
179
  uint32_t allowed_type_modifier= 0;
 
180
  uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
 
181
 
 
182
  field= 0;
 
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)
 
191
  {
 
192
    my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
 
193
             NOT_FIXED_DEC-1);
 
194
    return(true);
 
195
  }
 
196
 
 
197
  sql_type= fld_type;
 
198
  length= 0;
 
199
  change= fld_change;
 
200
  interval= 0;
 
201
  pack_length= key_length= 0;
 
202
  charset= fld_charset;
 
203
  interval_list.empty();
 
204
 
 
205
  comment= *fld_comment;
 
206
 
 
207
  /*
 
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.
 
210
  */
 
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;
 
214
 
 
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;
 
218
 
 
219
  switch (fld_type) 
 
220
  {
 
221
    case DRIZZLE_TYPE_TINY:
 
222
      if (!fld_length)
 
223
        length= MAX_TINYINT_WIDTH+sign_len;
 
224
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
 
225
      break;
 
226
    case DRIZZLE_TYPE_LONG:
 
227
      if (!fld_length)
 
228
        length= MAX_INT_WIDTH+sign_len;
 
229
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
 
230
      break;
 
231
    case DRIZZLE_TYPE_LONGLONG:
 
232
      if (!fld_length)
 
233
        length= MAX_BIGINT_WIDTH;
 
234
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
 
235
      break;
 
236
    case DRIZZLE_TYPE_NULL:
 
237
      break;
 
238
    case DRIZZLE_TYPE_NEWDECIMAL:
 
239
      my_decimal_trim(&length, &decimals);
 
240
      if (length > DECIMAL_MAX_PRECISION)
 
241
      {
 
242
        my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
 
243
                DECIMAL_MAX_PRECISION);
 
244
        return(true);
 
245
      }
 
246
      if (length < decimals)
 
247
      {
 
248
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
 
249
        return(true);
 
250
      }
 
251
      length= my_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
 
252
      pack_length= my_decimal_get_binary_size(length, decimals);
 
253
      break;
 
254
    case DRIZZLE_TYPE_VARCHAR:
 
255
      /*
 
256
        Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
 
257
        if they don't have a default value
 
258
      */
 
259
      max_field_charlength= MAX_FIELD_VARCHARLENGTH;
 
260
      break;
 
261
    case DRIZZLE_TYPE_BLOB:
 
262
      if (fld_default_value)
 
263
      {
 
264
        /* Allow empty as default value. */
 
265
        String str,*res;
 
266
        res= fld_default_value->val_str(&str);
 
267
        if (res->length())
 
268
        {
 
269
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
 
270
          return(true);
 
271
        }
 
272
 
 
273
      }
 
274
      flags|= BLOB_FLAG;
 
275
      break;
 
276
    case DRIZZLE_TYPE_DOUBLE:
 
277
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
 
278
      if (!fld_length && !fld_decimals)
 
279
      {
 
280
        length= DBL_DIG+7;
 
281
        decimals= NOT_FIXED_DEC;
 
282
      }
 
283
      if (length < decimals &&
 
284
          decimals != NOT_FIXED_DEC)
 
285
      {
 
286
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
 
287
        return(true);
 
288
      }
 
289
      break;
 
290
    case DRIZZLE_TYPE_TIMESTAMP:
 
291
      if (!fld_length)
 
292
      {
 
293
        /* Compressed date YYYYMMDDHHMMSS */
 
294
        length= MAX_DATETIME_COMPRESSED_WIDTH;
 
295
      }
 
296
      else if (length != MAX_DATETIME_WIDTH)
 
297
      {
 
298
        /*
 
299
          We support only even TIMESTAMP lengths less or equal than 14
 
300
          and 19 as length of 4.1 compatible representation.
 
301
        */
 
302
        length= ((length+1)/2)*2; /* purecov: inspected */
 
303
        length= cmin(length, (uint32_t)MAX_DATETIME_COMPRESSED_WIDTH); /* purecov: inspected */
 
304
      }
 
305
      flags|= UNSIGNED_FLAG;
 
306
      if (fld_default_value)
 
307
      {
 
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)
 
311
        {
 
312
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
 
313
                                              Field::TIMESTAMP_DN_FIELD);
 
314
          /*
 
315
            We don't need default value any longer moreover it is dangerous.
 
316
            Everything handled by unireg_check further.
 
317
          */
 
318
          def= 0;
 
319
        }
 
320
        else
 
321
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
 
322
                                              Field::NONE);
 
323
      }
 
324
      else
 
325
      {
 
326
        /*
 
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.
 
335
 
 
336
          If we have TIMESTAMP NULL column without explicit DEFAULT value
 
337
          we treat it as having DEFAULT NULL attribute.
 
338
        */
 
339
        unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
 
340
                      (flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
 
341
                                                Field::NONE));
 
342
      }
 
343
      break;
 
344
    case DRIZZLE_TYPE_DATE:
 
345
      length= 10;
 
346
      break;
 
347
    case DRIZZLE_TYPE_DATETIME:
 
348
      length= MAX_DATETIME_WIDTH;
 
349
      break;
 
350
    case DRIZZLE_TYPE_ENUM:
 
351
      {
 
352
        /* Should be safe. */
 
353
        pack_length= get_enum_pack_length(fld_interval_list->elements);
 
354
 
 
355
        List_iterator<String> it(*fld_interval_list);
 
356
        String *tmp;
 
357
        while ((tmp= it++))
 
358
          interval_list.push_back(tmp);
 
359
        length= 1;
 
360
        break;
 
361
    }
 
362
  }
 
363
  /* Remember the value of length */
 
364
  char_length= length;
 
365
 
 
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)))
 
371
  {
 
372
    my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ?  ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
 
373
              MYF(0),
 
374
              fld_name, max_field_charlength); /* purecov: inspected */
 
375
    return true;
 
376
  }
 
377
  fld_type_modifier&= AUTO_INCREMENT_FLAG;
 
378
  if ((~allowed_type_modifier) & fld_type_modifier)
 
379
  {
 
380
    my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
 
381
    return true;
 
382
  }
 
383
 
 
384
  return false; /* success */
 
385
}