~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)
1532.1.15 by Brian Aker
Partial encapsulation of TableShare from Table.
72
    pack_length= (pack_length - old_field->table->getShare()->blob_ptr_size + portable_sizeof_char_ptr);
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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 */
1574 by Brian Aker
Rollup patch for hiding tableshare.
106
    diff= (ptrdiff_t) (orig_field->table->getDefaultValues() - orig_field->table->record[0]);
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
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;
1119.9.18 by Stewart Smith
Fix maybe_null for CreateField created for temp table in item/sum.cc (Item_sum_distinct)
167
168
  if (! maybe_null)
169
    flags= NOT_NULL_FLAG;
170
  else
171
    flags= 0;
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
172
}
173
1052.2.7 by Nathan Williams
Merged trunk and resolved conflicts.
174
bool CreateField::init(Session *,
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
175
                        char *fld_name,
176
                        enum_field_types fld_type,
177
                        char *fld_length,
178
                        char *fld_decimals,
179
                        uint32_t fld_type_modifier,
180
                        Item *fld_default_value,
181
                        Item *fld_on_update_value,
182
                        LEX_STRING *fld_comment,
183
                        char *fld_change,
184
                        List<String> *fld_interval_list,
185
                        const CHARSET_INFO * const fld_charset,
186
                        uint32_t,
187
                        enum column_format_type column_format_in)
188
                        
189
{
190
  uint32_t sign_len= 0;
191
  uint32_t allowed_type_modifier= 0;
192
  uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
193
194
  field= 0;
195
  field_name= fld_name;
196
  def= fld_default_value;
197
  flags= fld_type_modifier;
198
  flags|= (((uint32_t)column_format_in & COLUMN_FORMAT_MASK) << COLUMN_FORMAT_FLAGS);
199
  unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
200
                 Field::NEXT_NUMBER : Field::NONE);
201
  decimals= fld_decimals ? (uint32_t)atoi(fld_decimals) : 0;
202
  if (decimals >= NOT_FIXED_DEC)
203
  {
204
    my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
205
             NOT_FIXED_DEC-1);
206
    return(true);
207
  }
208
209
  sql_type= fld_type;
210
  length= 0;
211
  change= fld_change;
212
  interval= 0;
213
  pack_length= key_length= 0;
214
  charset= fld_charset;
1101.1.24 by Monty Taylor
Reverted my change to interval_list
215
  interval_list.empty();
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
216
217
  comment= *fld_comment;
218
219
  /*
220
    Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
221
    it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
222
  */
223
  if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
224
      (fld_type_modifier & NOT_NULL_FLAG) && fld_type != DRIZZLE_TYPE_TIMESTAMP)
225
    flags|= NO_DEFAULT_VALUE_FLAG;
226
227
  if (fld_length && !(length= (uint32_t) atoi(fld_length)))
971.6.11 by Eric Day
Removed purecov messages.
228
    fld_length= 0;
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
229
  sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
230
231
  switch (fld_type) 
232
  {
233
    case DRIZZLE_TYPE_LONG:
234
      if (!fld_length)
235
        length= MAX_INT_WIDTH+sign_len;
236
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
237
      break;
238
    case DRIZZLE_TYPE_LONGLONG:
239
      if (!fld_length)
240
        length= MAX_BIGINT_WIDTH;
241
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
242
      break;
243
    case DRIZZLE_TYPE_NULL:
244
      break;
1211.1.1 by Brian Aker
Updating with my change to to DECIMAL from NEWDECIMAL and Stewart's update
245
    case DRIZZLE_TYPE_DECIMAL:
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
246
      my_decimal_trim(&length, &decimals);
247
      if (length > DECIMAL_MAX_PRECISION)
248
      {
249
        my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
250
                DECIMAL_MAX_PRECISION);
251
        return(true);
252
      }
253
      if (length < decimals)
254
      {
255
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
256
        return(true);
257
      }
258
      length= my_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
259
      pack_length= my_decimal_get_binary_size(length, decimals);
260
      break;
261
    case DRIZZLE_TYPE_VARCHAR:
262
      /*
263
        Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
264
        if they don't have a default value
265
      */
266
      max_field_charlength= MAX_FIELD_VARCHARLENGTH;
267
      break;
268
    case DRIZZLE_TYPE_BLOB:
269
      if (fld_default_value)
270
      {
271
        /* Allow empty as default value. */
272
        String str,*res;
273
        res= fld_default_value->val_str(&str);
274
        if (res->length())
275
        {
276
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
277
          return(true);
278
        }
279
280
      }
281
      flags|= BLOB_FLAG;
282
      break;
283
    case DRIZZLE_TYPE_DOUBLE:
284
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
285
      if (!fld_length && !fld_decimals)
286
      {
287
        length= DBL_DIG+7;
288
        decimals= NOT_FIXED_DEC;
289
      }
290
      if (length < decimals &&
291
          decimals != NOT_FIXED_DEC)
292
      {
293
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
294
        return(true);
295
      }
296
      break;
297
    case DRIZZLE_TYPE_TIMESTAMP:
298
      if (!fld_length)
299
      {
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
300
        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.
301
      }
302
303
      /* This assert() should be correct due to absence of length
304
         specifiers for timestamp. Previous manipulation also wasn't
305
         ever called (from examining lcov)
306
      */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
307
      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.
308
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
309
      flags|= UNSIGNED_FLAG;
310
      if (fld_default_value)
311
      {
312
        /* Grammar allows only NOW() value for ON UPDATE clause */
313
        if (fld_default_value->type() == Item::FUNC_ITEM &&
314
            ((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
315
        {
316
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
317
                                              Field::TIMESTAMP_DN_FIELD);
318
          /*
319
            We don't need default value any longer moreover it is dangerous.
320
            Everything handled by unireg_check further.
321
          */
322
          def= 0;
323
        }
324
        else
325
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
326
                                              Field::NONE);
327
      }
328
      else
329
      {
330
        /*
331
          If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
332
          or ON UPDATE values then for the sake of compatiblity we should treat
333
          this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
334
          have another TIMESTAMP column with auto-set option before this one)
335
          or DEFAULT 0 (in other cases).
336
          So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
337
          replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
338
          information about all TIMESTAMP fields in table will be availiable.
339
340
          If we have TIMESTAMP NULL column without explicit DEFAULT value
341
          we treat it as having DEFAULT NULL attribute.
342
        */
343
        unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
344
                      (flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
345
                                                Field::NONE));
346
      }
347
      break;
348
    case DRIZZLE_TYPE_DATE:
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
349
      length= Date::MAX_STRING_LENGTH;
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
350
      break;
351
    case DRIZZLE_TYPE_DATETIME:
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
352
      length= DateTime::MAX_STRING_LENGTH;
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
353
      break;
354
    case DRIZZLE_TYPE_ENUM:
355
      {
356
        /* Should be safe. */
357
        pack_length= get_enum_pack_length(fld_interval_list->elements);
358
359
        List_iterator<String> it(*fld_interval_list);
360
        String *tmp;
361
        while ((tmp= it++))
1101.1.24 by Monty Taylor
Reverted my change to interval_list
362
          interval_list.push_back(tmp);
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
363
        length= 1;
364
        break;
365
    }
366
  }
367
  /* Remember the value of length */
368
  char_length= length;
369
370
  if (!(flags & BLOB_FLAG) &&
371
      ((length > max_field_charlength &&
372
        fld_type != DRIZZLE_TYPE_ENUM &&
373
        (fld_type != DRIZZLE_TYPE_VARCHAR || fld_default_value)) ||
374
       (!length && fld_type != DRIZZLE_TYPE_VARCHAR)))
375
  {
376
    my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ?  ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
377
              MYF(0),
971.6.11 by Eric Day
Removed purecov messages.
378
              fld_name, max_field_charlength);
1055.2.10 by Jay Pipes
Moves Create_field implementation out into its own implementation file.
379
    return true;
380
  }
381
  fld_type_modifier&= AUTO_INCREMENT_FLAG;
382
  if ((~allowed_type_modifier) & fld_type_modifier)
383
  {
384
    my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
385
    return true;
386
  }
387
388
  return false; /* success */
389
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
390
391
} /* namespace drizzled */