~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/create_field.cc

  • Committer: Brian Aker
  • Date: 2008-10-06 06:47:29 UTC
  • Revision ID: brian@tangent.org-20081006064729-2i9mhjkzyvow9xsm
RemoveĀ uint.

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_NEWDECIMAL:
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, uint32_t decimals_arg,
154
 
                                      bool maybe_null, bool is_unsigned)
155
 
{
156
 
  field_name= "";
157
 
  sql_type= sql_type_arg;
158
 
  char_length= length= length_arg;;
159
 
  unireg_check= Field::NONE;
160
 
  interval= 0;
161
 
  charset= &my_charset_bin;
162
 
  pack_flag= (FIELDFLAG_NUMBER |
163
 
              ((decimals_arg & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT) |
164
 
              (maybe_null ? FIELDFLAG_MAYBE_NULL : 0) |
165
 
              (is_unsigned ? 0 : FIELDFLAG_DECIMAL));
166
 
}
167
 
 
168
 
bool CreateField::init(Session *,
169
 
                        char *fld_name,
170
 
                        enum_field_types fld_type,
171
 
                        char *fld_length,
172
 
                        char *fld_decimals,
173
 
                        uint32_t fld_type_modifier,
174
 
                        Item *fld_default_value,
175
 
                        Item *fld_on_update_value,
176
 
                        LEX_STRING *fld_comment,
177
 
                        char *fld_change,
178
 
                        List<String> *fld_interval_list,
179
 
                        const CHARSET_INFO * const fld_charset,
180
 
                        uint32_t,
181
 
                        enum column_format_type column_format_in)
182
 
                        
183
 
{
184
 
  uint32_t sign_len= 0;
185
 
  uint32_t allowed_type_modifier= 0;
186
 
  uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
187
 
 
188
 
  field= 0;
189
 
  field_name= fld_name;
190
 
  def= fld_default_value;
191
 
  flags= fld_type_modifier;
192
 
  flags|= (((uint32_t)column_format_in & COLUMN_FORMAT_MASK) << COLUMN_FORMAT_FLAGS);
193
 
  unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
194
 
                 Field::NEXT_NUMBER : Field::NONE);
195
 
  decimals= fld_decimals ? (uint32_t)atoi(fld_decimals) : 0;
196
 
  if (decimals >= NOT_FIXED_DEC)
197
 
  {
198
 
    my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
199
 
             NOT_FIXED_DEC-1);
200
 
    return(true);
201
 
  }
202
 
 
203
 
  sql_type= fld_type;
204
 
  length= 0;
205
 
  change= fld_change;
206
 
  interval= 0;
207
 
  pack_length= key_length= 0;
208
 
  charset= fld_charset;
209
 
  interval_list.empty();
210
 
 
211
 
  comment= *fld_comment;
212
 
 
213
 
  /*
214
 
    Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
215
 
    it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
216
 
  */
217
 
  if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
218
 
      (fld_type_modifier & NOT_NULL_FLAG) && fld_type != DRIZZLE_TYPE_TIMESTAMP)
219
 
    flags|= NO_DEFAULT_VALUE_FLAG;
220
 
 
221
 
  if (fld_length && !(length= (uint32_t) atoi(fld_length)))
222
 
    fld_length= 0;
223
 
  sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
224
 
 
225
 
  switch (fld_type) 
226
 
  {
227
 
    case DRIZZLE_TYPE_TINY:
228
 
      if (!fld_length)
229
 
        length= MAX_TINYINT_WIDTH+sign_len;
230
 
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
231
 
      break;
232
 
    case DRIZZLE_TYPE_LONG:
233
 
      if (!fld_length)
234
 
        length= MAX_INT_WIDTH+sign_len;
235
 
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
236
 
      break;
237
 
    case DRIZZLE_TYPE_LONGLONG:
238
 
      if (!fld_length)
239
 
        length= MAX_BIGINT_WIDTH;
240
 
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
241
 
      break;
242
 
    case DRIZZLE_TYPE_NULL:
243
 
      break;
244
 
    case DRIZZLE_TYPE_NEWDECIMAL:
245
 
      my_decimal_trim(&length, &decimals);
246
 
      if (length > DECIMAL_MAX_PRECISION)
247
 
      {
248
 
        my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
249
 
                DECIMAL_MAX_PRECISION);
250
 
        return(true);
251
 
      }
252
 
      if (length < decimals)
253
 
      {
254
 
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
255
 
        return(true);
256
 
      }
257
 
      length= my_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
258
 
      pack_length= my_decimal_get_binary_size(length, decimals);
259
 
      break;
260
 
    case DRIZZLE_TYPE_VARCHAR:
261
 
      /*
262
 
        Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
263
 
        if they don't have a default value
264
 
      */
265
 
      max_field_charlength= MAX_FIELD_VARCHARLENGTH;
266
 
      break;
267
 
    case DRIZZLE_TYPE_BLOB:
268
 
      if (fld_default_value)
269
 
      {
270
 
        /* Allow empty as default value. */
271
 
        String str,*res;
272
 
        res= fld_default_value->val_str(&str);
273
 
        if (res->length())
274
 
        {
275
 
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
276
 
          return(true);
277
 
        }
278
 
 
279
 
      }
280
 
      flags|= BLOB_FLAG;
281
 
      break;
282
 
    case DRIZZLE_TYPE_DOUBLE:
283
 
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
284
 
      if (!fld_length && !fld_decimals)
285
 
      {
286
 
        length= DBL_DIG+7;
287
 
        decimals= NOT_FIXED_DEC;
288
 
      }
289
 
      if (length < decimals &&
290
 
          decimals != NOT_FIXED_DEC)
291
 
      {
292
 
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
293
 
        return(true);
294
 
      }
295
 
      break;
296
 
    case DRIZZLE_TYPE_TIMESTAMP:
297
 
      if (!fld_length)
298
 
      {
299
 
        length= drizzled::DateTime::MAX_STRING_LENGTH;
300
 
      }
301
 
 
302
 
      /* This assert() should be correct due to absence of length
303
 
         specifiers for timestamp. Previous manipulation also wasn't
304
 
         ever called (from examining lcov)
305
 
      */
306
 
      assert(length == (uint32_t)drizzled::DateTime::MAX_STRING_LENGTH);
307
 
 
308
 
      flags|= UNSIGNED_FLAG;
309
 
      if (fld_default_value)
310
 
      {
311
 
        /* Grammar allows only NOW() value for ON UPDATE clause */
312
 
        if (fld_default_value->type() == Item::FUNC_ITEM &&
313
 
            ((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
314
 
        {
315
 
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
316
 
                                              Field::TIMESTAMP_DN_FIELD);
317
 
          /*
318
 
            We don't need default value any longer moreover it is dangerous.
319
 
            Everything handled by unireg_check further.
320
 
          */
321
 
          def= 0;
322
 
        }
323
 
        else
324
 
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
325
 
                                              Field::NONE);
326
 
      }
327
 
      else
328
 
      {
329
 
        /*
330
 
          If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
331
 
          or ON UPDATE values then for the sake of compatiblity we should treat
332
 
          this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
333
 
          have another TIMESTAMP column with auto-set option before this one)
334
 
          or DEFAULT 0 (in other cases).
335
 
          So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
336
 
          replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
337
 
          information about all TIMESTAMP fields in table will be availiable.
338
 
 
339
 
          If we have TIMESTAMP NULL column without explicit DEFAULT value
340
 
          we treat it as having DEFAULT NULL attribute.
341
 
        */
342
 
        unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
343
 
                      (flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
344
 
                                                Field::NONE));
345
 
      }
346
 
      break;
347
 
    case DRIZZLE_TYPE_DATE:
348
 
      length= drizzled::Date::MAX_STRING_LENGTH;
349
 
      break;
350
 
    case DRIZZLE_TYPE_DATETIME:
351
 
      length= drizzled::DateTime::MAX_STRING_LENGTH;
352
 
      break;
353
 
    case DRIZZLE_TYPE_ENUM:
354
 
      {
355
 
        /* Should be safe. */
356
 
        pack_length= get_enum_pack_length(fld_interval_list->elements);
357
 
 
358
 
        List_iterator<String> it(*fld_interval_list);
359
 
        String *tmp;
360
 
        while ((tmp= it++))
361
 
          interval_list.push_back(tmp);
362
 
        length= 1;
363
 
        break;
364
 
    }
365
 
  }
366
 
  /* Remember the value of length */
367
 
  char_length= length;
368
 
 
369
 
  if (!(flags & BLOB_FLAG) &&
370
 
      ((length > max_field_charlength &&
371
 
        fld_type != DRIZZLE_TYPE_ENUM &&
372
 
        (fld_type != DRIZZLE_TYPE_VARCHAR || fld_default_value)) ||
373
 
       (!length && fld_type != DRIZZLE_TYPE_VARCHAR)))
374
 
  {
375
 
    my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ?  ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
376
 
              MYF(0),
377
 
              fld_name, max_field_charlength);
378
 
    return true;
379
 
  }
380
 
  fld_type_modifier&= AUTO_INCREMENT_FLAG;
381
 
  if ((~allowed_type_modifier) & fld_type_modifier)
382
 
  {
383
 
    my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
384
 
    return true;
385
 
  }
386
 
 
387
 
  return false; /* success */
388
 
}