~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
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
24
#include "config.h"
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
25
#include <errno.h>
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
26
#include <float.h>
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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"
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.
46
#include "drizzled/temporal.h"
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
47
1067.4.1 by Nathan Williams
First few changes at converting cmin to std::min.
48
#include <algorithm>
49
50
using namespace std;
51
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
52
namespace drizzled
53
{
1067.4.1 by Nathan Williams
First few changes at converting cmin to std::min.
54
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
55
/** Create a field suitable for create of table. */
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
56
CreateField::CreateField(Field *old_field, Field *orig_field)
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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->table->s->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
1315.2.15 by Stewart Smith
remove the now unused SET_FLAG define. We don't have the SET field type, and this flag was never set.
90
  if (flags & ENUM_FLAG)
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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
      old_field->ptr && orig_field &&
99
      (sql_type != DRIZZLE_TYPE_TIMESTAMP ||                /* set def only if */
100
       old_field->table->timestamp_field != old_field ||  /* timestamp field */
101
       unireg_check == Field::TIMESTAMP_UN_FIELD))        /* has default val */
102
  {
103
    ptrdiff_t diff;
104
105
    /* Get the value from default_values */
106
    diff= (ptrdiff_t) (orig_field->table->s->default_values - orig_field->table->record[0]);
107
    orig_field->move_field_offset(diff);	// Points now at default_values
108
    if (! orig_field->is_real_null())
109
    {
110
      char buff[MAX_FIELD_WIDTH], *pos;
111
      String tmp(buff, sizeof(buff), charset), *res;
112
      res= orig_field->val_str(&tmp);
1253.1.6 by Monty Taylor
Moved mem_root functions into drizzled::memory:: namespace.
113
      pos= (char*) memory::sql_strmake(res->ptr(), res->length());
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
114
      def= new Item_string(pos, res->length(), charset);
115
    }
116
    orig_field->move_field_offset(-diff);	// Back to record[0]
117
  }
118
}
119
120
/**
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
121
  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.
122
*/
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
123
void CreateField::create_length_to_internal_length(void)
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
124
{
125
  switch (sql_type) 
126
  {
127
    case DRIZZLE_TYPE_BLOB:
128
    case DRIZZLE_TYPE_VARCHAR:
129
      length*= charset->mbmaxlen;
130
      key_length= length;
131
      pack_length= calc_pack_length(sql_type, length);
132
      break;
133
    case DRIZZLE_TYPE_ENUM:
134
      /* Pack_length already calculated in ::init() */
135
      length*= charset->mbmaxlen;
136
      key_length= pack_length;
137
      break;
1211.1.1 by Brian Aker
Updating with my change to to DECIMAL from NEWDECIMAL and Stewart's update
138
    case DRIZZLE_TYPE_DECIMAL:
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
139
      key_length= pack_length=
140
        my_decimal_get_binary_size(my_decimal_length_to_precision(length,
141
                  decimals,
142
                  flags &
143
                  UNSIGNED_FLAG),
144
          decimals);
145
      break;
146
    default:
147
      key_length= pack_length= calc_pack_length(sql_type, length);
148
      break;
149
  }
150
}
151
152
/**
153
  Init for a tmp table field. To be extended if need be.
154
*/
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
155
void CreateField::init_for_tmp_table(enum_field_types sql_type_arg,
1119.9.10 by Jay Pipes
Removes FIELDFLAG_MAYBE_NULL and f_maybe_null() macro.
156
                                     uint32_t length_arg,
157
                                     uint32_t decimals_arg,
1119.9.18 by Stewart Smith
Fix maybe_null for CreateField created for temp table in item/sum.cc (Item_sum_distinct)
158
                                     bool maybe_null)
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
159
{
160
  field_name= "";
161
  sql_type= sql_type_arg;
162
  char_length= length= length_arg;;
163
  unireg_check= Field::NONE;
164
  interval= 0;
165
  charset= &my_charset_bin;
1119.9.16 by Stewart Smith
don't store decimal/double scale in pack_flag, instead use the numeric option scale field in the table proto. This removes f_decimals() macro and the bits in the pack_flag for scale.
166
  decimals= decimals_arg & FIELDFLAG_MAX_DEC;
167
  pack_flag= 0;
1119.9.18 by Stewart Smith
Fix maybe_null for CreateField created for temp table in item/sum.cc (Item_sum_distinct)
168
169
  if (! maybe_null)
170
    flags= NOT_NULL_FLAG;
171
  else
172
    flags= 0;
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
173
}
174
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
175
bool CreateField::init(Session *,
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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;
1101.1.24 by Monty Taylor
Reverted my change to interval_list
216
  interval_list.empty();
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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)))
971.6.11 by Eric Day
Removed purecov messages.
229
    fld_length= 0;
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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;
1211.1.1 by Brian Aker
Updating with my change to to DECIMAL from NEWDECIMAL and Stewart's update
246
    case DRIZZLE_TYPE_DECIMAL:
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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
      {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
301
        length= DateTime::MAX_STRING_LENGTH;
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.
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
      */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
308
      assert(length == (uint32_t)DateTime::MAX_STRING_LENGTH);
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.
309
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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:
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
350
      length= Date::MAX_STRING_LENGTH;
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
351
      break;
352
    case DRIZZLE_TYPE_DATETIME:
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
353
      length= DateTime::MAX_STRING_LENGTH;
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
354
      break;
355
    case DRIZZLE_TYPE_ENUM:
356
      {
357
        /* Should be safe. */
358
        pack_length= get_enum_pack_length(fld_interval_list->elements);
359
360
        List_iterator<String> it(*fld_interval_list);
361
        String *tmp;
362
        while ((tmp= it++))
1101.1.24 by Monty Taylor
Reverted my change to interval_list
363
          interval_list.push_back(tmp);
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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),
971.6.11 by Eric Day
Removed purecov messages.
379
              fld_name, max_field_charlength);
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
391
392
} /* namespace drizzled */