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