~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/create_field.cc

Renamed more stuff to drizzle.

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