Drizzled Public API Documentation

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