~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/create_field.cc

pandora-build v0.72 - Moved remaining hard-coded tests into pandora-build
macros.
Add PANDORA_DRIZZLE_BUILD to run the extra checks that drizzle needs that 
plugins would also need to run so we can just use that macro in generated
external plugin builds.
Added support to register_plugins for external plugin building.
Renamed register_plugins.py to pandora-plugin.

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
}