~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/create_field.cc

  • Committer: Brian Aker
  • Date: 2011-02-22 06:12:02 UTC
  • mfrom: (2190.1.6 drizzle-build)
  • Revision ID: brian@tangent.org-20110222061202-k03czxykqy4x9hjs
List update, header fixes, multiple symbols, and David deletes some code.

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, Inc.
 
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 <config.h>
 
25
#include <errno.h>
 
26
#include <float.h>
 
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/boolean.h>
 
35
#include <drizzled/field/enum.h>
 
36
#include <drizzled/field/null.h>
 
37
#include <drizzled/field/date.h>
 
38
#include <drizzled/field/decimal.h>
 
39
#include <drizzled/field/real.h>
 
40
#include <drizzled/field/double.h>
 
41
#include <drizzled/field/int32.h>
 
42
#include <drizzled/field/int64.h>
 
43
#include <drizzled/field/num.h>
 
44
#include <drizzled/field/epoch.h>
 
45
#include <drizzled/field/datetime.h>
 
46
#include <drizzled/field/varstring.h>
 
47
#include <drizzled/field/uuid.h>
 
48
#include <drizzled/temporal.h>
 
49
#include <drizzled/item/string.h>
 
50
#include <drizzled/table.h>
 
51
 
 
52
#include <drizzled/display.h>
 
53
 
 
54
#include <algorithm>
 
55
 
 
56
using namespace std;
 
57
 
 
58
namespace drizzled
 
59
{
 
60
 
 
61
/** Create a field suitable for create of table. */
 
62
CreateField::CreateField(Field *old_field, Field *orig_field)
 
63
{
 
64
  field= old_field;
 
65
  field_name= change= old_field->field_name;
 
66
  length= old_field->field_length;
 
67
  flags= old_field->flags;
 
68
  unireg_check= old_field->unireg_check;
 
69
  pack_length= old_field->pack_length();
 
70
  key_length= old_field->key_length();
 
71
  sql_type= old_field->real_type();
 
72
  charset= old_field->charset(); // May be NULL ptr
 
73
  comment= old_field->comment;
 
74
  decimals= old_field->decimals();
 
75
 
 
76
  /* Fix if the original table had 4 byte pointer blobs */
 
77
  if (flags & BLOB_FLAG)
 
78
  {
 
79
    pack_length= (pack_length - old_field->getTable()->getShare()->sizeBlobPtr() + portable_sizeof_char_ptr);
 
80
  }
 
81
 
 
82
  switch (sql_type) 
 
83
  {
 
84
    case DRIZZLE_TYPE_BLOB:
 
85
      sql_type= DRIZZLE_TYPE_BLOB;
 
86
      length/= charset->mbmaxlen;
 
87
      key_length/= charset->mbmaxlen;
 
88
      break;
 
89
    case DRIZZLE_TYPE_ENUM:
 
90
    case DRIZZLE_TYPE_VARCHAR:
 
91
      /* This is corrected in create_length_to_internal_length */
 
92
      length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
 
93
      break;
 
94
    default:
 
95
      break;
 
96
  }
 
97
 
 
98
  if (flags & ENUM_FLAG)
 
99
    interval= ((Field_enum*) old_field)->typelib;
 
100
  else
 
101
    interval= 0;
 
102
  def= 0;
 
103
  char_length= length;
 
104
 
 
105
  if (!(flags & (NO_DEFAULT_VALUE_FLAG)) &&
 
106
      !(flags & AUTO_INCREMENT_FLAG) &&
 
107
      old_field->ptr && orig_field &&
 
108
      (not old_field->is_timestamp() ||                /* set def only if */
 
109
       old_field->getTable()->timestamp_field != old_field ||  /* timestamp field */
 
110
       unireg_check == Field::TIMESTAMP_UN_FIELD))        /* has default val */
 
111
  {
 
112
    ptrdiff_t diff;
 
113
 
 
114
    /* Get the value from default_values */
 
115
    diff= (ptrdiff_t) (orig_field->getTable()->getDefaultValues() - orig_field->getTable()->getInsertRecord());
 
116
    orig_field->move_field_offset(diff);        // Points now at default_values
 
117
    if (! orig_field->is_real_null())
 
118
    {
 
119
      char buff[MAX_FIELD_WIDTH], *pos;
 
120
      String tmp(buff, sizeof(buff), charset), *res;
 
121
      res= orig_field->val_str_internal(&tmp);
 
122
      pos= (char*) memory::sql_strmake(res->ptr(), res->length());
 
123
      def= new Item_string(pos, res->length(), charset);
 
124
    }
 
125
    orig_field->move_field_offset(-diff);       // Back to getInsertRecord()
 
126
  }
 
127
}
 
128
 
 
129
/**
 
130
  Convert CreateField::length from number of characters to number of bytes.
 
131
*/
 
132
void CreateField::create_length_to_internal_length(void)
 
133
{
 
134
  switch (sql_type) 
 
135
  {
 
136
    case DRIZZLE_TYPE_BLOB:
 
137
    case DRIZZLE_TYPE_VARCHAR:
 
138
      length*= charset->mbmaxlen;
 
139
      key_length= length;
 
140
      pack_length= calc_pack_length(sql_type, length);
 
141
      break;
 
142
    case DRIZZLE_TYPE_ENUM:
 
143
      /* Pack_length already calculated in ::init() */
 
144
      length*= charset->mbmaxlen;
 
145
      key_length= pack_length;
 
146
      break;
 
147
    case DRIZZLE_TYPE_DECIMAL:
 
148
      key_length= pack_length=
 
149
        class_decimal_get_binary_size(class_decimal_length_to_precision(length,
 
150
                  decimals,
 
151
                  flags &
 
152
                  UNSIGNED_FLAG),
 
153
          decimals);
 
154
      break;
 
155
    default:
 
156
      key_length= pack_length= calc_pack_length(sql_type, length);
 
157
      break;
 
158
  }
 
159
}
 
160
 
 
161
/**
 
162
  Init for a tmp table field. To be extended if need be.
 
163
*/
 
164
void CreateField::init_for_tmp_table(enum_field_types sql_type_arg,
 
165
                                     uint32_t length_arg,
 
166
                                     uint32_t decimals_arg,
 
167
                                     bool maybe_null)
 
168
{
 
169
  field_name= "";
 
170
  sql_type= sql_type_arg;
 
171
  char_length= length= length_arg;;
 
172
  unireg_check= Field::NONE;
 
173
  interval= 0;
 
174
  charset= &my_charset_bin;
 
175
  decimals= decimals_arg & FIELDFLAG_MAX_DEC;
 
176
 
 
177
  if (! maybe_null)
 
178
    flags= NOT_NULL_FLAG;
 
179
  else
 
180
    flags= 0;
 
181
}
 
182
 
 
183
bool CreateField::init(Session *,
 
184
                        char *fld_name,
 
185
                        enum_field_types fld_type,
 
186
                        char *fld_length,
 
187
                        char *fld_decimals,
 
188
                        uint32_t fld_type_modifier,
 
189
                        Item *fld_default_value,
 
190
                        Item *fld_on_update_value,
 
191
                        LEX_STRING *fld_comment,
 
192
                        char *fld_change,
 
193
                        List<String> *fld_interval_list,
 
194
                        const CHARSET_INFO * const fld_charset,
 
195
                        uint32_t,
 
196
                        enum column_format_type column_format_in)
 
197
                        
 
198
{
 
199
  uint32_t sign_len= 0;
 
200
  uint32_t allowed_type_modifier= 0;
 
201
  uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
 
202
 
 
203
  field= 0;
 
204
  field_name= fld_name;
 
205
  def= fld_default_value;
 
206
  flags= fld_type_modifier;
 
207
  flags|= (((uint32_t)column_format_in & COLUMN_FORMAT_MASK) << COLUMN_FORMAT_FLAGS);
 
208
  unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
 
209
                 Field::NEXT_NUMBER : Field::NONE);
 
210
  decimals= fld_decimals ? (uint32_t)atoi(fld_decimals) : 0;
 
211
  if (decimals >= NOT_FIXED_DEC)
 
212
  {
 
213
    my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
 
214
             NOT_FIXED_DEC-1);
 
215
    return(true);
 
216
  }
 
217
 
 
218
  sql_type= fld_type;
 
219
  length= 0;
 
220
  change= fld_change;
 
221
  interval= 0;
 
222
  pack_length= key_length= 0;
 
223
  charset= fld_charset;
 
224
  interval_list.clear();
 
225
 
 
226
  comment= *fld_comment;
 
227
 
 
228
  /*
 
229
    Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
 
230
    it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
 
231
  */
 
232
  if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
 
233
      (fld_type_modifier & NOT_NULL_FLAG) && (fld_type != DRIZZLE_TYPE_TIMESTAMP and fld_type != DRIZZLE_TYPE_MICROTIME))
 
234
  {
 
235
    flags|= NO_DEFAULT_VALUE_FLAG;
 
236
  }
 
237
 
 
238
  if (fld_length && !(length= (uint32_t) atoi(fld_length)))
 
239
    fld_length= 0;
 
240
  sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
 
241
 
 
242
  switch (fld_type) 
 
243
  {
 
244
    case DRIZZLE_TYPE_LONG:
 
245
      if (!fld_length)
 
246
        length= MAX_INT_WIDTH+sign_len;
 
247
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
 
248
      break;
 
249
    case DRIZZLE_TYPE_LONGLONG:
 
250
      if (!fld_length)
 
251
        length= MAX_BIGINT_WIDTH;
 
252
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
 
253
      break;
 
254
    case DRIZZLE_TYPE_NULL:
 
255
      break;
 
256
    case DRIZZLE_TYPE_DECIMAL:
 
257
      class_decimal_trim(&length, &decimals);
 
258
      if (length > DECIMAL_MAX_PRECISION)
 
259
      {
 
260
        my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
 
261
                DECIMAL_MAX_PRECISION);
 
262
        return(true);
 
263
      }
 
264
      if (length < decimals)
 
265
      {
 
266
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
 
267
        return(true);
 
268
      }
 
269
      length= class_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
 
270
      pack_length= class_decimal_get_binary_size(length, decimals);
 
271
      break;
 
272
    case DRIZZLE_TYPE_VARCHAR:
 
273
      /*
 
274
        Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
 
275
        if they don't have a default value
 
276
      */
 
277
      max_field_charlength= MAX_FIELD_VARCHARLENGTH;
 
278
      break;
 
279
    case DRIZZLE_TYPE_BLOB:
 
280
      if (fld_default_value)
 
281
      {
 
282
        /* Allow empty as default value. */
 
283
        String str,*res;
 
284
        res= fld_default_value->val_str(&str);
 
285
        if (res->length())
 
286
        {
 
287
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
 
288
          return(true);
 
289
        }
 
290
 
 
291
      }
 
292
      flags|= BLOB_FLAG;
 
293
      break;
 
294
    case DRIZZLE_TYPE_DOUBLE:
 
295
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
 
296
      if (!fld_length && !fld_decimals)
 
297
      {
 
298
        length= DBL_DIG+7;
 
299
        decimals= NOT_FIXED_DEC;
 
300
      }
 
301
      if (length < decimals &&
 
302
          decimals != NOT_FIXED_DEC)
 
303
      {
 
304
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
 
305
        return(true);
 
306
      }
 
307
      break;
 
308
    case DRIZZLE_TYPE_MICROTIME:
 
309
      /* 
 
310
        This assert() should be correct due to absence of length
 
311
        specifiers for timestamp. Previous manipulation also wasn't
 
312
        ever called (from examining lcov)
 
313
      */
 
314
      assert(fld_type);
 
315
    case DRIZZLE_TYPE_TIMESTAMP:
 
316
      length= MicroTimestamp::MAX_STRING_LENGTH;
 
317
 
 
318
      if (fld_default_value)
 
319
      {
 
320
        /* Grammar allows only NOW() value for ON UPDATE clause */
 
321
        if (fld_default_value->type() == Item::FUNC_ITEM &&
 
322
            ((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
 
323
        {
 
324
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
 
325
                                              Field::TIMESTAMP_DN_FIELD);
 
326
          /*
 
327
            We don't need default value any longer moreover it is dangerous.
 
328
            Everything handled by unireg_check further.
 
329
          */
 
330
          def= 0;
 
331
        }
 
332
        else
 
333
        {
 
334
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
 
335
                         Field::NONE);
 
336
        }
 
337
      }
 
338
      else
 
339
      {
 
340
        /*
 
341
          If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
 
342
          or ON UPDATE values then for the sake of compatiblity we should treat
 
343
          this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
 
344
          have another TIMESTAMP column with auto-set option before this one)
 
345
          or DEFAULT 0 (in other cases).
 
346
          So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
 
347
          replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
 
348
          information about all TIMESTAMP fields in table will be availiable.
 
349
 
 
350
          If we have TIMESTAMP NULL column without explicit DEFAULT value
 
351
          we treat it as having DEFAULT NULL attribute.
 
352
        */
 
353
        unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
 
354
                      (flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
 
355
                                                Field::NONE));
 
356
      }
 
357
      break;
 
358
    case DRIZZLE_TYPE_DATE:
 
359
      length= Date::MAX_STRING_LENGTH;
 
360
      break;
 
361
    case DRIZZLE_TYPE_UUID:
 
362
      length= field::Uuid::max_string_length();
 
363
      break;
 
364
    case DRIZZLE_TYPE_BOOLEAN:
 
365
      length= field::Boolean::max_string_length();
 
366
      break;
 
367
    case DRIZZLE_TYPE_DATETIME:
 
368
      length= DateTime::MAX_STRING_LENGTH;
 
369
      break;
 
370
    case DRIZZLE_TYPE_TIME:
 
371
      length= DateTime::MAX_STRING_LENGTH;
 
372
      break;
 
373
    case DRIZZLE_TYPE_ENUM:
 
374
      {
 
375
        /* Should be safe. */
 
376
        pack_length= 4;
 
377
 
 
378
        List<String>::iterator it(fld_interval_list->begin());
 
379
        String *tmp;
 
380
        while ((tmp= it++))
 
381
          interval_list.push_back(tmp);
 
382
        length= 1;
 
383
        break;
 
384
    }
 
385
  }
 
386
  /* Remember the value of length */
 
387
  char_length= length;
 
388
 
 
389
  if (!(flags & BLOB_FLAG) &&
 
390
      ((length > max_field_charlength &&
 
391
        fld_type != DRIZZLE_TYPE_ENUM &&
 
392
        (fld_type != DRIZZLE_TYPE_VARCHAR || fld_default_value)) ||
 
393
       (!length && fld_type != DRIZZLE_TYPE_VARCHAR)))
 
394
  {
 
395
    my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ?  ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
 
396
              MYF(0),
 
397
              fld_name, max_field_charlength);
 
398
    return true;
 
399
  }
 
400
  fld_type_modifier&= AUTO_INCREMENT_FLAG;
 
401
  if ((~allowed_type_modifier) & fld_type_modifier)
 
402
  {
 
403
    my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
 
404
    return true;
 
405
  }
 
406
 
 
407
  return false; /* success */
 
408
}
 
409
 
 
410
std::ostream& operator<<(std::ostream& output, const CreateField &field)
 
411
{
 
412
  output << "CreateField:(";
 
413
  output <<  field.field_name;
 
414
  output << ", ";
 
415
  output << drizzled::display::type(field.type());
 
416
  output << ", { ";
 
417
 
 
418
  if (field.flags & NOT_NULL_FLAG)
 
419
    output << " NOT_NULL";
 
420
 
 
421
  if (field.flags & PRI_KEY_FLAG)
 
422
    output << ", PRIMARY KEY";
 
423
 
 
424
  if (field.flags & UNIQUE_KEY_FLAG)
 
425
    output << ", UNIQUE KEY";
 
426
 
 
427
  if (field.flags & MULTIPLE_KEY_FLAG)
 
428
    output << ", MULTIPLE KEY";
 
429
 
 
430
  if (field.flags & BLOB_FLAG)
 
431
    output << ", BLOB";
 
432
 
 
433
  if (field.flags & UNSIGNED_FLAG)
 
434
    output << ", UNSIGNED";
 
435
 
 
436
  if (field.flags & BINARY_FLAG)
 
437
    output << ", BINARY";
 
438
  output << "}, ";
 
439
  if (field.field)
 
440
    output << *field.field;
 
441
  output << ")";
 
442
 
 
443
  return output;  // for multiple << operators.
 
444
}
 
445
 
 
446
} /* namespace drizzled */