~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/create_field.cc

  • Committer: Monty Taylor
  • Date: 2009-04-20 14:42:34 UTC
  • mto: (997.2.5 mordred)
  • mto: This revision was merged to the branch mainline in revision 1003.
  • Revision ID: mordred@inaugust.com-20090420144234-4k1x60fiag2l1y0n
Ported InnoDB to register_plugins.

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
 
#include "drizzled/temporal.h"
46
 
 
47
 
#include <algorithm>
48
 
 
49
 
using namespace std;
50
 
 
51
 
 
52
 
/** Create a field suitable for create of table. */
53
 
CreateField::CreateField(Field *old_field, Field *orig_field)
54
 
{
55
 
  field= old_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();
66
 
 
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);
70
 
 
71
 
  switch (sql_type) 
72
 
  {
73
 
    case DRIZZLE_TYPE_BLOB:
74
 
      sql_type= DRIZZLE_TYPE_BLOB;
75
 
      length/= charset->mbmaxlen;
76
 
      key_length/= charset->mbmaxlen;
77
 
      break;
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;
82
 
      break;
83
 
    default:
84
 
      break;
85
 
  }
86
 
 
87
 
  if (flags & (ENUM_FLAG | SET_FLAG))
88
 
    interval= ((Field_enum*) old_field)->typelib;
89
 
  else
90
 
    interval= 0;
91
 
  def= 0;
92
 
  char_length= length;
93
 
 
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 */
99
 
  {
100
 
    ptrdiff_t diff;
101
 
 
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())
106
 
    {
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);
112
 
    }
113
 
    orig_field->move_field_offset(-diff);       // Back to record[0]
114
 
  }
115
 
}
116
 
 
117
 
/**
118
 
  Convert CreateField::length from number of characters to number of bytes.
119
 
*/
120
 
void CreateField::create_length_to_internal_length(void)
121
 
{
122
 
  switch (sql_type) 
123
 
  {
124
 
    case DRIZZLE_TYPE_BLOB:
125
 
    case DRIZZLE_TYPE_VARCHAR:
126
 
      length*= charset->mbmaxlen;
127
 
      key_length= length;
128
 
      pack_length= calc_pack_length(sql_type, length);
129
 
      break;
130
 
    case DRIZZLE_TYPE_ENUM:
131
 
      /* Pack_length already calculated in ::init() */
132
 
      length*= charset->mbmaxlen;
133
 
      key_length= pack_length;
134
 
      break;
135
 
    case DRIZZLE_TYPE_DECIMAL:
136
 
      key_length= pack_length=
137
 
        my_decimal_get_binary_size(my_decimal_length_to_precision(length,
138
 
                  decimals,
139
 
                  flags &
140
 
                  UNSIGNED_FLAG),
141
 
          decimals);
142
 
      break;
143
 
    default:
144
 
      key_length= pack_length= calc_pack_length(sql_type, length);
145
 
      break;
146
 
  }
147
 
}
148
 
 
149
 
/**
150
 
  Init for a tmp table field. To be extended if need be.
151
 
*/
152
 
void CreateField::init_for_tmp_table(enum_field_types sql_type_arg,
153
 
                                     uint32_t length_arg,
154
 
                                     uint32_t decimals_arg,
155
 
                                     bool maybe_null)
156
 
{
157
 
  field_name= "";
158
 
  sql_type= sql_type_arg;
159
 
  char_length= length= length_arg;;
160
 
  unireg_check= Field::NONE;
161
 
  interval= 0;
162
 
  charset= &my_charset_bin;
163
 
  decimals= decimals_arg & FIELDFLAG_MAX_DEC;
164
 
  pack_flag= 0;
165
 
 
166
 
  if (! maybe_null)
167
 
    flags= NOT_NULL_FLAG;
168
 
  else
169
 
    flags= 0;
170
 
}
171
 
 
172
 
bool CreateField::init(Session *,
173
 
                        char *fld_name,
174
 
                        enum_field_types fld_type,
175
 
                        char *fld_length,
176
 
                        char *fld_decimals,
177
 
                        uint32_t fld_type_modifier,
178
 
                        Item *fld_default_value,
179
 
                        Item *fld_on_update_value,
180
 
                        LEX_STRING *fld_comment,
181
 
                        char *fld_change,
182
 
                        List<String> *fld_interval_list,
183
 
                        const CHARSET_INFO * const fld_charset,
184
 
                        uint32_t,
185
 
                        enum column_format_type column_format_in)
186
 
                        
187
 
{
188
 
  uint32_t sign_len= 0;
189
 
  uint32_t allowed_type_modifier= 0;
190
 
  uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
191
 
 
192
 
  field= 0;
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)
201
 
  {
202
 
    my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
203
 
             NOT_FIXED_DEC-1);
204
 
    return(true);
205
 
  }
206
 
 
207
 
  sql_type= fld_type;
208
 
  length= 0;
209
 
  change= fld_change;
210
 
  interval= 0;
211
 
  pack_length= key_length= 0;
212
 
  charset= fld_charset;
213
 
  interval_list.empty();
214
 
 
215
 
  comment= *fld_comment;
216
 
 
217
 
  /*
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.
220
 
  */
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;
224
 
 
225
 
  if (fld_length && !(length= (uint32_t) atoi(fld_length)))
226
 
    fld_length= 0;
227
 
  sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
228
 
 
229
 
  switch (fld_type) 
230
 
  {
231
 
    case DRIZZLE_TYPE_LONG:
232
 
      if (!fld_length)
233
 
        length= MAX_INT_WIDTH+sign_len;
234
 
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
235
 
      break;
236
 
    case DRIZZLE_TYPE_LONGLONG:
237
 
      if (!fld_length)
238
 
        length= MAX_BIGINT_WIDTH;
239
 
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
240
 
      break;
241
 
    case DRIZZLE_TYPE_NULL:
242
 
      break;
243
 
    case DRIZZLE_TYPE_DECIMAL:
244
 
      my_decimal_trim(&length, &decimals);
245
 
      if (length > DECIMAL_MAX_PRECISION)
246
 
      {
247
 
        my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
248
 
                DECIMAL_MAX_PRECISION);
249
 
        return(true);
250
 
      }
251
 
      if (length < decimals)
252
 
      {
253
 
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
254
 
        return(true);
255
 
      }
256
 
      length= my_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
257
 
      pack_length= my_decimal_get_binary_size(length, decimals);
258
 
      break;
259
 
    case DRIZZLE_TYPE_VARCHAR:
260
 
      /*
261
 
        Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
262
 
        if they don't have a default value
263
 
      */
264
 
      max_field_charlength= MAX_FIELD_VARCHARLENGTH;
265
 
      break;
266
 
    case DRIZZLE_TYPE_BLOB:
267
 
      if (fld_default_value)
268
 
      {
269
 
        /* Allow empty as default value. */
270
 
        String str,*res;
271
 
        res= fld_default_value->val_str(&str);
272
 
        if (res->length())
273
 
        {
274
 
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
275
 
          return(true);
276
 
        }
277
 
 
278
 
      }
279
 
      flags|= BLOB_FLAG;
280
 
      break;
281
 
    case DRIZZLE_TYPE_DOUBLE:
282
 
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
283
 
      if (!fld_length && !fld_decimals)
284
 
      {
285
 
        length= DBL_DIG+7;
286
 
        decimals= NOT_FIXED_DEC;
287
 
      }
288
 
      if (length < decimals &&
289
 
          decimals != NOT_FIXED_DEC)
290
 
      {
291
 
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
292
 
        return(true);
293
 
      }
294
 
      break;
295
 
    case DRIZZLE_TYPE_TIMESTAMP:
296
 
      if (!fld_length)
297
 
      {
298
 
        length= drizzled::DateTime::MAX_STRING_LENGTH;
299
 
      }
300
 
 
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)
304
 
      */
305
 
      assert(length == (uint32_t)drizzled::DateTime::MAX_STRING_LENGTH);
306
 
 
307
 
      flags|= UNSIGNED_FLAG;
308
 
      if (fld_default_value)
309
 
      {
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)
313
 
        {
314
 
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
315
 
                                              Field::TIMESTAMP_DN_FIELD);
316
 
          /*
317
 
            We don't need default value any longer moreover it is dangerous.
318
 
            Everything handled by unireg_check further.
319
 
          */
320
 
          def= 0;
321
 
        }
322
 
        else
323
 
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
324
 
                                              Field::NONE);
325
 
      }
326
 
      else
327
 
      {
328
 
        /*
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.
337
 
 
338
 
          If we have TIMESTAMP NULL column without explicit DEFAULT value
339
 
          we treat it as having DEFAULT NULL attribute.
340
 
        */
341
 
        unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
342
 
                      (flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
343
 
                                                Field::NONE));
344
 
      }
345
 
      break;
346
 
    case DRIZZLE_TYPE_DATE:
347
 
      length= drizzled::Date::MAX_STRING_LENGTH;
348
 
      break;
349
 
    case DRIZZLE_TYPE_DATETIME:
350
 
      length= drizzled::DateTime::MAX_STRING_LENGTH;
351
 
      break;
352
 
    case DRIZZLE_TYPE_ENUM:
353
 
      {
354
 
        /* Should be safe. */
355
 
        pack_length= get_enum_pack_length(fld_interval_list->elements);
356
 
 
357
 
        List_iterator<String> it(*fld_interval_list);
358
 
        String *tmp;
359
 
        while ((tmp= it++))
360
 
          interval_list.push_back(tmp);
361
 
        length= 1;
362
 
        break;
363
 
    }
364
 
  }
365
 
  /* Remember the value of length */
366
 
  char_length= length;
367
 
 
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)))
373
 
  {
374
 
    my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ?  ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
375
 
              MYF(0),
376
 
              fld_name, max_field_charlength);
377
 
    return true;
378
 
  }
379
 
  fld_type_modifier&= AUTO_INCREMENT_FLAG;
380
 
  if ((~allowed_type_modifier) & fld_type_modifier)
381
 
  {
382
 
    my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
383
 
    return true;
384
 
  }
385
 
 
386
 
  return false; /* success */
387
 
}