~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/create_field.cc

code clean move Item_func_ascii, Item_func_bit_count, Item_func_find_in_set, Item_func_ord  to functions directory

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, Inc.
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 <config.h>
25
 
#include <errno.h>
26
 
#include <float.h>
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/boolean.h>
35
 
#include <drizzled/field/enum.h>
36
 
#include <drizzled/field/null.h>
37
 
#include <drizzled/field/date.h>
38
 
#include <drizzled/field/decimal.h>
39
 
#include <drizzled/field/real.h>
40
 
#include <drizzled/field/double.h>
41
 
#include <drizzled/field/int32.h>
42
 
#include <drizzled/field/int64.h>
43
 
#include <drizzled/field/num.h>
44
 
#include <drizzled/field/epoch.h>
45
 
#include <drizzled/field/datetime.h>
46
 
#include <drizzled/field/varstring.h>
47
 
#include <drizzled/field/uuid.h>
48
 
#include <drizzled/temporal.h>
49
 
#include <drizzled/item/string.h>
50
 
#include <drizzled/table.h>
51
 
 
52
 
#include <drizzled/display.h>
53
 
 
54
 
#include <algorithm>
55
 
 
56
 
using namespace std;
57
 
 
58
 
namespace drizzled
59
 
{
60
 
 
61
 
/** Create a field suitable for create of table. */
62
 
CreateField::CreateField(Field *old_field, Field *orig_field)
63
 
{
64
 
  field= old_field;
65
 
  field_name= change= old_field->field_name;
66
 
  length= old_field->field_length;
67
 
  flags= old_field->flags;
68
 
  unireg_check= old_field->unireg_check;
69
 
  pack_length= old_field->pack_length();
70
 
  key_length= old_field->key_length();
71
 
  sql_type= old_field->real_type();
72
 
  charset= old_field->charset(); // May be NULL ptr
73
 
  comment= old_field->comment;
74
 
  decimals= old_field->decimals();
75
 
 
76
 
  /* Fix if the original table had 4 byte pointer blobs */
77
 
  if (flags & BLOB_FLAG)
78
 
  {
79
 
    pack_length= (pack_length - old_field->getTable()->getShare()->sizeBlobPtr() + portable_sizeof_char_ptr);
80
 
  }
81
 
 
82
 
  switch (sql_type) 
83
 
  {
84
 
    case DRIZZLE_TYPE_BLOB:
85
 
      sql_type= DRIZZLE_TYPE_BLOB;
86
 
      length/= charset->mbmaxlen;
87
 
      key_length/= charset->mbmaxlen;
88
 
      break;
89
 
    case DRIZZLE_TYPE_ENUM:
90
 
    case DRIZZLE_TYPE_VARCHAR:
91
 
      /* This is corrected in create_length_to_internal_length */
92
 
      length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
93
 
      break;
94
 
    default:
95
 
      break;
96
 
  }
97
 
 
98
 
  if (flags & ENUM_FLAG)
99
 
    interval= ((Field_enum*) old_field)->typelib;
100
 
  else
101
 
    interval= 0;
102
 
  def= 0;
103
 
  char_length= length;
104
 
 
105
 
  if (!(flags & (NO_DEFAULT_VALUE_FLAG)) &&
106
 
      !(flags & AUTO_INCREMENT_FLAG) &&
107
 
      old_field->ptr && orig_field &&
108
 
      (not old_field->is_timestamp() ||                /* set def only if */
109
 
       old_field->getTable()->timestamp_field != old_field ||  /* timestamp field */
110
 
       unireg_check == Field::TIMESTAMP_UN_FIELD))        /* has default val */
111
 
  {
112
 
    ptrdiff_t diff;
113
 
 
114
 
    /* Get the value from default_values */
115
 
    diff= (ptrdiff_t) (orig_field->getTable()->getDefaultValues() - orig_field->getTable()->getInsertRecord());
116
 
    orig_field->move_field_offset(diff);        // Points now at default_values
117
 
    if (! orig_field->is_real_null())
118
 
    {
119
 
      char buff[MAX_FIELD_WIDTH], *pos;
120
 
      String tmp(buff, sizeof(buff), charset), *res;
121
 
      res= orig_field->val_str_internal(&tmp);
122
 
      pos= (char*) memory::sql_strmake(res->ptr(), res->length());
123
 
      def= new Item_string(pos, res->length(), charset);
124
 
    }
125
 
    orig_field->move_field_offset(-diff);       // Back to getInsertRecord()
126
 
  }
127
 
}
128
 
 
129
 
/**
130
 
  Convert CreateField::length from number of characters to number of bytes.
131
 
*/
132
 
void CreateField::create_length_to_internal_length(void)
133
 
{
134
 
  switch (sql_type) 
135
 
  {
136
 
    case DRIZZLE_TYPE_BLOB:
137
 
    case DRIZZLE_TYPE_VARCHAR:
138
 
      length*= charset->mbmaxlen;
139
 
      key_length= length;
140
 
      pack_length= calc_pack_length(sql_type, length);
141
 
      break;
142
 
    case DRIZZLE_TYPE_ENUM:
143
 
      /* Pack_length already calculated in ::init() */
144
 
      length*= charset->mbmaxlen;
145
 
      key_length= pack_length;
146
 
      break;
147
 
    case DRIZZLE_TYPE_DECIMAL:
148
 
      key_length= pack_length=
149
 
        class_decimal_get_binary_size(class_decimal_length_to_precision(length,
150
 
                  decimals,
151
 
                  flags &
152
 
                  UNSIGNED_FLAG),
153
 
          decimals);
154
 
      break;
155
 
    default:
156
 
      key_length= pack_length= calc_pack_length(sql_type, length);
157
 
      break;
158
 
  }
159
 
}
160
 
 
161
 
/**
162
 
  Init for a tmp table field. To be extended if need be.
163
 
*/
164
 
void CreateField::init_for_tmp_table(enum_field_types sql_type_arg,
165
 
                                     uint32_t length_arg,
166
 
                                     uint32_t decimals_arg,
167
 
                                     bool maybe_null)
168
 
{
169
 
  field_name= "";
170
 
  sql_type= sql_type_arg;
171
 
  char_length= length= length_arg;;
172
 
  unireg_check= Field::NONE;
173
 
  interval= 0;
174
 
  charset= &my_charset_bin;
175
 
  decimals= decimals_arg & FIELDFLAG_MAX_DEC;
176
 
 
177
 
  if (! maybe_null)
178
 
    flags= NOT_NULL_FLAG;
179
 
  else
180
 
    flags= 0;
181
 
}
182
 
 
183
 
bool CreateField::init(Session *,
184
 
                        char *fld_name,
185
 
                        enum_field_types fld_type,
186
 
                        char *fld_length,
187
 
                        char *fld_decimals,
188
 
                        uint32_t fld_type_modifier,
189
 
                        Item *fld_default_value,
190
 
                        Item *fld_on_update_value,
191
 
                        LEX_STRING *fld_comment,
192
 
                        char *fld_change,
193
 
                        List<String> *fld_interval_list,
194
 
                        const CHARSET_INFO * const fld_charset,
195
 
                        uint32_t,
196
 
                        enum column_format_type column_format_in)
197
 
                        
198
 
{
199
 
  uint32_t sign_len= 0;
200
 
  uint32_t allowed_type_modifier= 0;
201
 
  uint32_t max_field_charlength= MAX_FIELD_CHARLENGTH;
202
 
 
203
 
  field= 0;
204
 
  field_name= fld_name;
205
 
  def= fld_default_value;
206
 
  flags= fld_type_modifier;
207
 
  flags|= (((uint32_t)column_format_in & COLUMN_FORMAT_MASK) << COLUMN_FORMAT_FLAGS);
208
 
  unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
209
 
                 Field::NEXT_NUMBER : Field::NONE);
210
 
  decimals= fld_decimals ? (uint32_t)atoi(fld_decimals) : 0;
211
 
  if (decimals >= NOT_FIXED_DEC)
212
 
  {
213
 
    my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
214
 
             NOT_FIXED_DEC-1);
215
 
    return(true);
216
 
  }
217
 
 
218
 
  sql_type= fld_type;
219
 
  length= 0;
220
 
  change= fld_change;
221
 
  interval= 0;
222
 
  pack_length= key_length= 0;
223
 
  charset= fld_charset;
224
 
  interval_list.clear();
225
 
 
226
 
  comment= *fld_comment;
227
 
 
228
 
  /*
229
 
    Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
230
 
    it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
231
 
  */
232
 
  if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
233
 
      (fld_type_modifier & NOT_NULL_FLAG) && (fld_type != DRIZZLE_TYPE_TIMESTAMP and fld_type != DRIZZLE_TYPE_MICROTIME))
234
 
  {
235
 
    flags|= NO_DEFAULT_VALUE_FLAG;
236
 
  }
237
 
 
238
 
  if (fld_length && !(length= (uint32_t) atoi(fld_length)))
239
 
    fld_length= 0;
240
 
  sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
241
 
 
242
 
  switch (fld_type) 
243
 
  {
244
 
    case DRIZZLE_TYPE_LONG:
245
 
      if (!fld_length)
246
 
        length= MAX_INT_WIDTH+sign_len;
247
 
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
248
 
      break;
249
 
    case DRIZZLE_TYPE_LONGLONG:
250
 
      if (!fld_length)
251
 
        length= MAX_BIGINT_WIDTH;
252
 
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
253
 
      break;
254
 
    case DRIZZLE_TYPE_NULL:
255
 
      break;
256
 
    case DRIZZLE_TYPE_DECIMAL:
257
 
      class_decimal_trim(&length, &decimals);
258
 
      if (length > DECIMAL_MAX_PRECISION)
259
 
      {
260
 
        my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
261
 
                DECIMAL_MAX_PRECISION);
262
 
        return(true);
263
 
      }
264
 
      if (length < decimals)
265
 
      {
266
 
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
267
 
        return(true);
268
 
      }
269
 
      length= class_decimal_precision_to_length(length, decimals, fld_type_modifier & UNSIGNED_FLAG);
270
 
      pack_length= class_decimal_get_binary_size(length, decimals);
271
 
      break;
272
 
    case DRIZZLE_TYPE_VARCHAR:
273
 
      /*
274
 
        Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
275
 
        if they don't have a default value
276
 
      */
277
 
      max_field_charlength= MAX_FIELD_VARCHARLENGTH;
278
 
      break;
279
 
    case DRIZZLE_TYPE_BLOB:
280
 
      if (fld_default_value)
281
 
      {
282
 
        /* Allow empty as default value. */
283
 
        String str,*res;
284
 
        res= fld_default_value->val_str(&str);
285
 
        if (res->length())
286
 
        {
287
 
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), fld_name);
288
 
          return(true);
289
 
        }
290
 
 
291
 
      }
292
 
      flags|= BLOB_FLAG;
293
 
      break;
294
 
    case DRIZZLE_TYPE_DOUBLE:
295
 
      allowed_type_modifier= AUTO_INCREMENT_FLAG;
296
 
      if (!fld_length && !fld_decimals)
297
 
      {
298
 
        length= DBL_DIG+7;
299
 
        decimals= NOT_FIXED_DEC;
300
 
      }
301
 
      if (length < decimals &&
302
 
          decimals != NOT_FIXED_DEC)
303
 
      {
304
 
        my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
305
 
        return(true);
306
 
      }
307
 
      break;
308
 
    case DRIZZLE_TYPE_MICROTIME:
309
 
      /* 
310
 
        This assert() should be correct due to absence of length
311
 
        specifiers for timestamp. Previous manipulation also wasn't
312
 
        ever called (from examining lcov)
313
 
      */
314
 
      assert(fld_type);
315
 
    case DRIZZLE_TYPE_TIMESTAMP:
316
 
      length= MicroTimestamp::MAX_STRING_LENGTH;
317
 
 
318
 
      if (fld_default_value)
319
 
      {
320
 
        /* Grammar allows only NOW() value for ON UPDATE clause */
321
 
        if (fld_default_value->type() == Item::FUNC_ITEM &&
322
 
            ((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
323
 
        {
324
 
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
325
 
                                              Field::TIMESTAMP_DN_FIELD);
326
 
          /*
327
 
            We don't need default value any longer moreover it is dangerous.
328
 
            Everything handled by unireg_check further.
329
 
          */
330
 
          def= 0;
331
 
        }
332
 
        else
333
 
        {
334
 
          unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
335
 
                         Field::NONE);
336
 
        }
337
 
      }
338
 
      else
339
 
      {
340
 
        /*
341
 
          If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
342
 
          or ON UPDATE values then for the sake of compatiblity we should treat
343
 
          this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
344
 
          have another TIMESTAMP column with auto-set option before this one)
345
 
          or DEFAULT 0 (in other cases).
346
 
          So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
347
 
          replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
348
 
          information about all TIMESTAMP fields in table will be availiable.
349
 
 
350
 
          If we have TIMESTAMP NULL column without explicit DEFAULT value
351
 
          we treat it as having DEFAULT NULL attribute.
352
 
        */
353
 
        unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
354
 
                      (flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
355
 
                                                Field::NONE));
356
 
      }
357
 
      break;
358
 
    case DRIZZLE_TYPE_DATE:
359
 
      length= Date::MAX_STRING_LENGTH;
360
 
      break;
361
 
    case DRIZZLE_TYPE_UUID:
362
 
      length= field::Uuid::max_string_length();
363
 
      break;
364
 
    case DRIZZLE_TYPE_BOOLEAN:
365
 
      length= field::Boolean::max_string_length();
366
 
      break;
367
 
    case DRIZZLE_TYPE_DATETIME:
368
 
      length= DateTime::MAX_STRING_LENGTH;
369
 
      break;
370
 
    case DRIZZLE_TYPE_TIME:
371
 
      length= DateTime::MAX_STRING_LENGTH;
372
 
      break;
373
 
    case DRIZZLE_TYPE_ENUM:
374
 
      {
375
 
        /* Should be safe. */
376
 
        pack_length= 4;
377
 
 
378
 
        List<String>::iterator it(fld_interval_list->begin());
379
 
        String *tmp;
380
 
        while ((tmp= it++))
381
 
          interval_list.push_back(tmp);
382
 
        length= 1;
383
 
        break;
384
 
    }
385
 
  }
386
 
  /* Remember the value of length */
387
 
  char_length= length;
388
 
 
389
 
  if (!(flags & BLOB_FLAG) &&
390
 
      ((length > max_field_charlength &&
391
 
        fld_type != DRIZZLE_TYPE_ENUM &&
392
 
        (fld_type != DRIZZLE_TYPE_VARCHAR || fld_default_value)) ||
393
 
       (!length && fld_type != DRIZZLE_TYPE_VARCHAR)))
394
 
  {
395
 
    my_error((fld_type == DRIZZLE_TYPE_VARCHAR) ?  ER_TOO_BIG_FIELDLENGTH : ER_TOO_BIG_DISPLAYWIDTH,
396
 
              MYF(0),
397
 
              fld_name, max_field_charlength);
398
 
    return true;
399
 
  }
400
 
  fld_type_modifier&= AUTO_INCREMENT_FLAG;
401
 
  if ((~allowed_type_modifier) & fld_type_modifier)
402
 
  {
403
 
    my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
404
 
    return true;
405
 
  }
406
 
 
407
 
  return false; /* success */
408
 
}
409
 
 
410
 
std::ostream& operator<<(std::ostream& output, const CreateField &field)
411
 
{
412
 
  output << "CreateField:(";
413
 
  output <<  field.field_name;
414
 
  output << ", ";
415
 
  output << drizzled::display::type(field.type());
416
 
  output << ", { ";
417
 
 
418
 
  if (field.flags & NOT_NULL_FLAG)
419
 
    output << " NOT_NULL";
420
 
 
421
 
  if (field.flags & PRI_KEY_FLAG)
422
 
    output << ", PRIMARY KEY";
423
 
 
424
 
  if (field.flags & UNIQUE_KEY_FLAG)
425
 
    output << ", UNIQUE KEY";
426
 
 
427
 
  if (field.flags & MULTIPLE_KEY_FLAG)
428
 
    output << ", MULTIPLE KEY";
429
 
 
430
 
  if (field.flags & BLOB_FLAG)
431
 
    output << ", BLOB";
432
 
 
433
 
  if (field.flags & UNSIGNED_FLAG)
434
 
    output << ", UNSIGNED";
435
 
 
436
 
  if (field.flags & BINARY_FLAG)
437
 
    output << ", BINARY";
438
 
  output << "}, ";
439
 
  if (field.field)
440
 
    output << *field.field;
441
 
  output << ")";
442
 
 
443
 
  return output;  // for multiple << operators.
444
 
}
445
 
 
446
 
} /* namespace drizzled */