~drizzle-trunk/drizzle/development

1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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
/**
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
21
 * @file Implementation of CreateField class
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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"
1079.3.2 by Stewart Smith
Replace MAX_(DATE|TIME).*_WIDTH defines in definitions.h with real (and correct) static const members to Temporal types.
45
#include "drizzled/temporal.h"
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
46
1067.4.1 by Nathan Williams
First few changes at converting cmin to std::min.
47
#include <algorithm>
48
49
using namespace std;
50
51
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
52
/** Create a field suitable for create of table. */
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
53
CreateField::CreateField(Field *old_field, Field *orig_field)
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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
/**
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
118
  Convert CreateField::length from number of characters to number of bytes.
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
119
*/
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
120
void CreateField::create_length_to_internal_length(void)
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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
*/
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
152
void CreateField::init_for_tmp_table(enum_field_types sql_type_arg,
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
168
bool CreateField::init(Session *,
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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;
1101.1.24 by Monty Taylor
Reverted my change to interval_list
209
  interval_list.empty();
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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; /* purecov: inspected */
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
      {
1079.3.2 by Stewart Smith
Replace MAX_(DATE|TIME).*_WIDTH defines in definitions.h with real (and correct) static const members to Temporal types.
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
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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:
1079.3.2 by Stewart Smith
Replace MAX_(DATE|TIME).*_WIDTH defines in definitions.h with real (and correct) static const members to Temporal types.
348
      length= drizzled::Date::MAX_STRING_LENGTH;
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
349
      break;
350
    case DRIZZLE_TYPE_DATETIME:
1079.3.2 by Stewart Smith
Replace MAX_(DATE|TIME).*_WIDTH defines in definitions.h with real (and correct) static const members to Temporal types.
351
      length= drizzled::DateTime::MAX_STRING_LENGTH;
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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++))
1101.1.24 by Monty Taylor
Reverted my change to interval_list
361
          interval_list.push_back(tmp);
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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); /* purecov: inspected */
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
}