Drizzled Public API Documentation

base.cc
1 /* -*- mode: c++; c-basic-offset: 2; i/dent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2010 Brian Aker
5  * Copyright (C) 2009 Sun Microsystems, Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /*
23  This class is shared between different table objects. There is one
24  instance of table share per one table in the database.
25 */
26 
27 /* Basic functions needed by many modules */
28 #include <config.h>
29 
30 #include <pthread.h>
31 #include <float.h>
32 
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 
37 
38 #include <cassert>
39 
40 #include <drizzled/error.h>
41 #include <drizzled/gettext.h>
42 #include <drizzled/sql_base.h>
43 #include <drizzled/pthread_globals.h>
44 #include <drizzled/internal/my_pthread.h>
45 
46 #include <drizzled/table.h>
47 #include <drizzled/table/shell.h>
48 
49 #include <drizzled/session.h>
50 
51 #include <drizzled/charset.h>
52 #include <drizzled/internal/m_string.h>
53 #include <drizzled/internal/my_sys.h>
54 
55 #include <drizzled/item/string.h>
56 #include <drizzled/item/int.h>
57 #include <drizzled/item/decimal.h>
58 #include <drizzled/item/float.h>
59 #include <drizzled/item/null.h>
60 #include <drizzled/temporal.h>
61 
62 #include <drizzled/field.h>
63 #include <drizzled/field/str.h>
64 #include <drizzled/field/num.h>
65 #include <drizzled/field/blob.h>
66 #include <drizzled/field/boolean.h>
67 #include <drizzled/field/enum.h>
68 #include <drizzled/field/null.h>
69 #include <drizzled/field/date.h>
70 #include <drizzled/field/decimal.h>
71 #include <drizzled/field/real.h>
72 #include <drizzled/field/double.h>
73 #include <drizzled/field/int32.h>
74 #include <drizzled/field/int64.h>
75 #include <drizzled/field/size.h>
76 #include <drizzled/field/num.h>
77 #include <drizzled/field/time.h>
78 #include <drizzled/field/epoch.h>
79 #include <drizzled/field/datetime.h>
80 #include <drizzled/field/microtime.h>
81 #include <drizzled/field/varstring.h>
82 #include <drizzled/field/uuid.h>
83 #include <drizzled/field/ipv6.h>
84 #include <drizzled/plugin/storage_engine.h>
85 #include <drizzled/definition/cache.h>
86 #include <drizzled/typelib.h>
87 #include <drizzled/key.h>
88 #include <drizzled/open_tables_state.h>
89 
90 using namespace std;
91 
92 namespace drizzled {
93 
94 extern size_t table_def_size;
95 
96 static enum_field_types proto_field_type_to_drizzle_type(const message::Table::Field &field)
97 {
98  switch(field.type())
99  {
100  case message::Table::Field::INTEGER:
101  return DRIZZLE_TYPE_LONG;
102 
103  case message::Table::Field::DOUBLE:
104  return DRIZZLE_TYPE_DOUBLE;
105 
106  case message::Table::Field::EPOCH:
107  if (field.has_time_options() and field.time_options().microseconds())
108  return DRIZZLE_TYPE_MICROTIME;
109 
110  return DRIZZLE_TYPE_TIMESTAMP;
111 
112  case message::Table::Field::BIGINT:
113  return DRIZZLE_TYPE_LONGLONG;
114 
115  case message::Table::Field::DATETIME:
116  return DRIZZLE_TYPE_DATETIME;
117 
118  case message::Table::Field::DATE:
119  return DRIZZLE_TYPE_DATE;
120 
121  case message::Table::Field::VARCHAR:
122  return DRIZZLE_TYPE_VARCHAR;
123 
124  case message::Table::Field::DECIMAL:
125  return DRIZZLE_TYPE_DECIMAL;
126 
127  case message::Table::Field::ENUM:
128  return DRIZZLE_TYPE_ENUM;
129 
130  case message::Table::Field::BLOB:
131  return DRIZZLE_TYPE_BLOB;
132 
133  case message::Table::Field::UUID:
134  return DRIZZLE_TYPE_UUID;
135 
136  case message::Table::Field::IPV6:
137  return DRIZZLE_TYPE_IPV6;
138 
139  case message::Table::Field::BOOLEAN:
140  return DRIZZLE_TYPE_BOOLEAN;
141 
142  case message::Table::Field::TIME:
143  return DRIZZLE_TYPE_TIME;
144  }
145 
146  abort();
147 }
148 
149 static Item* default_value_item(enum_field_types field_type, const charset_info_st& charset, bool default_null,
150  const string& default_value, const string& default_bin_value)
151 {
152  if (default_null)
153  return new Item_null();
154 
155  switch (field_type)
156  {
157  case DRIZZLE_TYPE_LONG:
158  case DRIZZLE_TYPE_LONGLONG:
159  {
160  int error= 0;
161  Item* default_item= new Item_int(default_value.c_str(), (int64_t) internal::my_strtoll10(default_value.c_str(), NULL, &error), default_value.length());
162 
163  if (error && error != -1) /* was an error and wasn't a negative number */
164  {
165  delete default_item;
166  return NULL;
167  }
168  return default_item;
169  }
170  case DRIZZLE_TYPE_DOUBLE:
171  return new Item_float(default_value.c_str(), default_value.length());
172  case DRIZZLE_TYPE_NULL:
173  assert(false);
174  abort();
175  case DRIZZLE_TYPE_TIMESTAMP:
176  case DRIZZLE_TYPE_DATETIME:
177  case DRIZZLE_TYPE_TIME:
178  case DRIZZLE_TYPE_DATE:
179  case DRIZZLE_TYPE_ENUM:
180  case DRIZZLE_TYPE_UUID:
181  case DRIZZLE_TYPE_IPV6:
182  case DRIZZLE_TYPE_MICROTIME:
183  case DRIZZLE_TYPE_BOOLEAN:
184  // return new Item_string(*default_value, system_charset_info); // crash
185  return new Item_string(default_value.data(), default_value.size(), system_charset_info);
186  case DRIZZLE_TYPE_VARCHAR:
187  case DRIZZLE_TYPE_BLOB: /* Blob is here due to TINYTEXT. Feel the hate. */
188  return &charset== &my_charset_bin
189  ? new Item_string(default_bin_value, &my_charset_bin)
190  : new Item_string(default_value, system_charset_info);
191  case DRIZZLE_TYPE_DECIMAL:
192  return new Item_decimal(default_value.c_str(), default_value.length(), system_charset_info);
193  }
194  return NULL;
195 }
196 
197 
198 
204 bool TableShare::fieldInPrimaryKey(Field *in_field) const
205 {
206  assert(getTableMessage());
207 
208  size_t num_indexes= getTableMessage()->indexes_size();
209 
210  for (size_t x= 0; x < num_indexes; ++x)
211  {
212  const message::Table::Index &index= getTableMessage()->indexes(x);
213  if (index.is_primary())
214  {
215  size_t num_parts= index.index_part_size();
216  for (size_t y= 0; y < num_parts; ++y)
217  {
218  if (index.index_part(y).fieldnr() == in_field->position())
219  return true;
220  }
221  }
222  }
223  return false;
224 }
225 
226 TableShare::TableShare(const identifier::Table::Type type_arg) :
227  table_category(TABLE_UNKNOWN_CATEGORY),
228  found_next_number_field(NULL),
229  timestamp_field(NULL),
230  key_info(NULL),
231  mem_root(TABLE_ALLOC_BLOCK_SIZE),
232  all_set(),
233  block_size(0),
234  version(0),
235  timestamp_offset(0),
236  reclength(0),
237  stored_rec_length(0),
238  max_rows(0),
239  _table_message(NULL),
240  storage_engine(NULL),
241  tmp_table(type_arg),
242  _ref_count(0),
243  null_bytes(0),
244  last_null_bit_pos(0),
245  _field_size(0),
246  rec_buff_length(0),
247  keys(0),
248  key_parts(0),
249  max_key_length(0),
250  max_unique_length(0),
251  total_key_length(0),
252  uniques(0),
253  null_fields(0),
254  blob_fields(0),
255  has_variable_width(false),
256  db_create_options(0),
257  db_options_in_use(0),
258  db_record_offset(0),
259  rowid_field_offset(0),
260  primary_key(MAX_KEY),
261  next_number_index(0),
262  next_number_key_offset(0),
263  next_number_keypart(0),
264  error(0),
265  open_errno(0),
266  errarg(0),
267  blob_ptr_size(portable_sizeof_char_ptr),
268  db_low_byte_first(false),
269  keys_in_use(0),
270  keys_for_keyread(0)
271 {
272  if (type_arg == message::Table::INTERNAL)
273  {
274  string s= identifier::Table::build_tmptable_filename();
275  private_key_for_cache.vectorPtr().assign(s.c_str(), s.c_str() + s.size() + 1);
276  init(private_key_for_cache.vector(), private_key_for_cache.vector());
277  }
278  else
279  {
280  init("", "");
281  }
282 }
283 
284 TableShare::TableShare(const identifier::Table &identifier, const identifier::Table::Key &key) :// Used by placeholder
285  table_category(TABLE_UNKNOWN_CATEGORY),
286  found_next_number_field(NULL),
287  timestamp_field(NULL),
288  key_info(NULL),
289  mem_root(TABLE_ALLOC_BLOCK_SIZE),
290  table_charset(0),
291  all_set(),
292  block_size(0),
293  version(0),
294  timestamp_offset(0),
295  reclength(0),
296  stored_rec_length(0),
297  max_rows(0),
298  _table_message(NULL),
299  storage_engine(NULL),
300  tmp_table(message::Table::INTERNAL),
301  _ref_count(0),
302  null_bytes(0),
303  last_null_bit_pos(0),
304  _field_size(0),
305  rec_buff_length(0),
306  keys(0),
307  key_parts(0),
308  max_key_length(0),
309  max_unique_length(0),
310  total_key_length(0),
311  uniques(0),
312  null_fields(0),
313  blob_fields(0),
314  has_variable_width(false),
315  db_create_options(0),
316  db_options_in_use(0),
317  db_record_offset(0),
318  rowid_field_offset(0),
319  primary_key(MAX_KEY),
320  next_number_index(0),
321  next_number_key_offset(0),
322  next_number_keypart(0),
323  error(0),
324  open_errno(0),
325  errarg(0),
326  blob_ptr_size(portable_sizeof_char_ptr),
327  db_low_byte_first(false),
328  keys_in_use(0),
329  keys_for_keyread(0)
330 {
331  assert(identifier.getKey() == key);
332 
333  private_key_for_cache= key;
334 
336  tmp_table= message::Table::INTERNAL;
337 
338  db= str_ref(private_key_for_cache.schema_name());
339  table_name= str_ref(private_key_for_cache.table_name());
340  path= str_ref("");
341  normalized_path= str_ref("");
342 
343  std::string tb_name(identifier.getTableName());
344  boost::to_lower(tb_name);
345  assert(strcmp(tb_name.c_str(), table_name.data()) == 0);
346 }
347 
348 TableShare::TableShare(const identifier::Table &identifier) : // Just used during createTable()
349  table_category(TABLE_UNKNOWN_CATEGORY),
350  found_next_number_field(NULL),
351  timestamp_field(NULL),
352  key_info(NULL),
353  mem_root(TABLE_ALLOC_BLOCK_SIZE),
354  table_charset(0),
355  all_set(),
356  block_size(0),
357  version(0),
358  timestamp_offset(0),
359  reclength(0),
360  stored_rec_length(0),
361  max_rows(0),
362  _table_message(NULL),
363  storage_engine(NULL),
364  tmp_table(identifier.getType()),
365  _ref_count(0),
366  null_bytes(0),
367  last_null_bit_pos(0),
368  _field_size(0),
369  rec_buff_length(0),
370  keys(0),
371  key_parts(0),
372  max_key_length(0),
373  max_unique_length(0),
374  total_key_length(0),
375  uniques(0),
376  null_fields(0),
377  blob_fields(0),
378  has_variable_width(false),
379  db_create_options(0),
380  db_options_in_use(0),
381  db_record_offset(0),
382  rowid_field_offset(0),
383  primary_key(MAX_KEY),
384  next_number_index(0),
385  next_number_key_offset(0),
386  next_number_keypart(0),
387  error(0),
388  open_errno(0),
389  errarg(0),
390  blob_ptr_size(portable_sizeof_char_ptr),
391  db_low_byte_first(false),
392  keys_in_use(0),
393  keys_for_keyread(0)
394 {
395  private_key_for_cache= identifier.getKey();
396  assert(identifier.getPath().size()); // Since we are doing a create table, this should be a positive value
397  private_normalized_path.resize(identifier.getPath().size() + 1);
398  memcpy(&private_normalized_path[0], identifier.getPath().c_str(), identifier.getPath().size());
399 
400  {
402  tmp_table= message::Table::INTERNAL;
403  db= str_ref(private_key_for_cache.vector());
404  table_name= str_ref(db.data() + 1);
405  path= private_normalized_path;
406  normalized_path= path;
407  }
408 }
409 
410 
411 /*
412  Used for shares that will go into the cache.
413 */
414 TableShare::TableShare(const identifier::Table::Type type_arg,
415  const identifier::Table &identifier,
416  const char *path_arg,
417  uint32_t path_length_arg) :
418  table_category(TABLE_UNKNOWN_CATEGORY),
419  found_next_number_field(NULL),
420  timestamp_field(NULL),
421  key_info(NULL),
422  mem_root(TABLE_ALLOC_BLOCK_SIZE),
423  table_charset(0),
424  all_set(),
425  block_size(0),
426  version(0),
427  timestamp_offset(0),
428  reclength(0),
429  stored_rec_length(0),
430  max_rows(0),
431  _table_message(NULL),
432  storage_engine(NULL),
433  tmp_table(type_arg),
434  _ref_count(0),
435  null_bytes(0),
436  last_null_bit_pos(0),
437  _field_size(0),
438  rec_buff_length(0),
439  keys(0),
440  key_parts(0),
441  max_key_length(0),
442  max_unique_length(0),
443  total_key_length(0),
444  uniques(0),
445  null_fields(0),
446  blob_fields(0),
447  has_variable_width(false),
448  db_create_options(0),
449  db_options_in_use(0),
450  db_record_offset(0),
451  rowid_field_offset(0),
452  primary_key(MAX_KEY),
453  next_number_index(0),
454  next_number_key_offset(0),
455  next_number_keypart(0),
456  error(0),
457  open_errno(0),
458  errarg(0),
459  blob_ptr_size(portable_sizeof_char_ptr),
460  db_low_byte_first(false),
461  keys_in_use(0),
462  keys_for_keyread(0)
463 {
464  private_key_for_cache= identifier.getKey();
465  /*
466  Let us use the fact that the key is "db/0/table_name/0" + optional
467  part for temporary tables.
468  */
469  db= str_ref(private_key_for_cache.schema_name());
470  table_name= str_ref(private_key_for_cache.table_name());
471 
472  std::string _path;
473  if (path_arg)
474  {
475  _path.assign(path_arg, path_length_arg);
476  }
477  else
478  {
479  _path= identifier::Table::build_table_filename(db.data(), table_name.data(), false);
480  }
481 
482  char* path_buff= mem_root.strdup(_path);
483  path= str_ref(path_buff, _path.length());
484  normalized_path= str_ref(path_buff, _path.length());
485 
486  version= g_refresh_version;
487 }
488 
489 void TableShare::init(const char *new_table_name, const char *new_path)
490 {
492  tmp_table= message::Table::INTERNAL;
493  db= str_ref("");
494  table_name= str_ref(new_table_name);
495  path= str_ref(new_path);
496  normalized_path= str_ref(new_path);
497 }
498 
499 TableShare::~TableShare()
500 {
501  storage_engine= NULL;
502 
503  mem_root.free_root(MYF(0)); // Free's share
504 }
505 
506 void TableShare::setIdentifier(const identifier::Table &identifier_arg)
507 {
508  private_key_for_cache= identifier_arg.getKey();
509 
510  /*
511  Let us use the fact that the key is "db/0/table_name/0" + optional
512  part for temporary tables.
513  */
514  db= str_ref(private_key_for_cache.schema_name());
515  table_name= str_ref(private_key_for_cache.table_name());
516 
517  getTableMessage()->set_name(identifier_arg.getTableName());
518  getTableMessage()->set_schema(identifier_arg.getSchemaName());
519 }
520 
521 bool TableShare::parse_table_proto(Session& session, const message::Table &table)
522 {
523  drizzled::error_t local_error= EE_OK;
524 
525  if (! table.IsInitialized())
526  {
527  my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
528  table.name().empty() ? " " : table.name().c_str(),
529  table.InitializationErrorString().c_str());
530 
531  return ER_CORRUPT_TABLE_DEFINITION;
532  }
533 
534  setTableMessage(table);
535 
536  storage_engine= plugin::StorageEngine::findByName(session, table.engine().name());
537  assert(storage_engine); // We use an assert() here because we should never get this far and still have no suitable engine.
538 
539  message::Table::TableOptions table_options;
540 
541  if (table.has_options())
542  table_options= table.options();
543 
544  uint32_t local_db_create_options= 0;
545 
546  if (table_options.pack_record())
547  local_db_create_options|= HA_OPTION_PACK_RECORD;
548 
549  /* local_db_create_options was stored as 2 bytes in FRM
550  Any HA_OPTION_ that doesn't fit into 2 bytes was silently truncated away.
551  */
552  db_create_options= (local_db_create_options & 0x0000FFFF);
553  db_options_in_use= db_create_options;
554 
555  block_size= table_options.has_block_size() ? table_options.block_size() : 0;
556 
557  table_charset= get_charset(table_options.collation_id());
558 
559  if (not table_charset)
560  {
561  my_error(ER_CORRUPT_TABLE_DEFINITION_UNKNOWN_COLLATION, MYF(0),
562  table_options.collation().c_str(),
563  table.name().c_str());
564 
565  return ER_CORRUPT_TABLE_DEFINITION; // Historical
566  }
567 
568  db_record_offset= 1;
569 
570  keys= table.indexes_size();
571 
572  key_parts= 0;
573  for (int indx= 0; indx < table.indexes_size(); indx++)
574  key_parts+= table.indexes(indx).index_part_size();
575 
576  key_info= (KeyInfo*) mem().alloc(table.indexes_size() * sizeof(KeyInfo) +key_parts*sizeof(KeyPartInfo));
577 
578  KeyPartInfo *key_part;
579 
580  key_part= reinterpret_cast<KeyPartInfo*>
581  (key_info+table.indexes_size());
582 
583 
584  ulong *rec_per_key= (ulong*) mem().alloc(sizeof(ulong*)*key_parts);
585 
586  KeyInfo* keyinfo= key_info;
587  for (int keynr= 0; keynr < table.indexes_size(); keynr++, keyinfo++)
588  {
589  message::Table::Index indx= table.indexes(keynr);
590 
591  keyinfo->table= 0;
592  keyinfo->flags= 0;
593 
594  if (indx.is_unique())
595  keyinfo->flags|= HA_NOSAME;
596 
597  if (indx.has_options())
598  {
599  message::Table::Index::Options indx_options= indx.options();
600  if (indx_options.pack_key())
601  keyinfo->flags|= HA_PACK_KEY;
602 
603  if (indx_options.var_length_key())
604  keyinfo->flags|= HA_VAR_LENGTH_PART;
605 
606  if (indx_options.null_part_key())
607  keyinfo->flags|= HA_NULL_PART_KEY;
608 
609  if (indx_options.binary_pack_key())
610  keyinfo->flags|= HA_BINARY_PACK_KEY;
611 
612  if (indx_options.has_partial_segments())
613  keyinfo->flags|= HA_KEY_HAS_PART_KEY_SEG;
614 
615  if (indx_options.auto_generated_key())
616  keyinfo->flags|= HA_GENERATED_KEY;
617 
618  if (indx_options.has_key_block_size())
619  {
620  keyinfo->flags|= HA_USES_BLOCK_SIZE;
621  keyinfo->block_size= indx_options.key_block_size();
622  }
623  else
624  {
625  keyinfo->block_size= 0;
626  }
627  }
628 
629  switch (indx.type())
630  {
631  case message::Table::Index::UNKNOWN_INDEX:
632  keyinfo->algorithm= HA_KEY_ALG_UNDEF;
633  break;
634  case message::Table::Index::BTREE:
635  keyinfo->algorithm= HA_KEY_ALG_BTREE;
636  break;
637  case message::Table::Index::HASH:
638  keyinfo->algorithm= HA_KEY_ALG_HASH;
639  break;
640 
641  default:
642  /* TODO: suitable warning ? */
643  keyinfo->algorithm= HA_KEY_ALG_UNDEF;
644  break;
645  }
646 
647  keyinfo->key_length= indx.key_length();
648 
649  keyinfo->key_parts= indx.index_part_size();
650 
651  keyinfo->key_part= key_part;
652  keyinfo->rec_per_key= rec_per_key;
653 
654  for (unsigned int partnr= 0;
655  partnr < keyinfo->key_parts;
656  partnr++, key_part++)
657  {
658  message::Table::Index::IndexPart part;
659  part= indx.index_part(partnr);
660 
661  *rec_per_key++= 0;
662 
663  key_part->field= NULL;
664  key_part->fieldnr= part.fieldnr() + 1; // start from 1.
665  key_part->null_bit= 0;
666  /* key_part->null_offset is only set if null_bit (see later) */
667  /* key_part->key_type= */ /* I *THINK* this may be okay.... */
668  /* key_part->type ???? */
669  key_part->key_part_flag= 0;
670  if (part.has_in_reverse_order())
671  key_part->key_part_flag= part.in_reverse_order()? HA_REVERSE_SORT : 0;
672 
673  key_part->length= part.compare_length();
674 
675  int mbmaxlen= 1;
676 
677  if (table.field(part.fieldnr()).type() == message::Table::Field::VARCHAR
678  || table.field(part.fieldnr()).type() == message::Table::Field::BLOB)
679  {
680  uint32_t collation_id;
681 
682  if (table.field(part.fieldnr()).string_options().has_collation_id())
683  collation_id= table.field(part.fieldnr()).string_options().collation_id();
684  else
685  collation_id= table.options().collation_id();
686 
687  const charset_info_st *cs= get_charset(collation_id);
688 
689  mbmaxlen= cs->mbmaxlen;
690  }
691  key_part->length*= mbmaxlen;
692 
693  key_part->store_length= key_part->length;
694 
695  /* key_part->offset is set later */
696  key_part->key_type= 0;
697  }
698 
699  if (not indx.has_comment())
700  {
701  keyinfo->comment.clear();
702  }
703  else
704  {
705  keyinfo->flags|= HA_USES_COMMENT;
706  keyinfo->comment.assign(mem().strdup(indx.comment()), indx.comment().length());
707  }
708 
709  keyinfo->name= mem().strdup(indx.name());
710 
711  addKeyName(string(keyinfo->name, indx.name().length()));
712  }
713 
714  keys_for_keyread.reset();
715  set_prefix(keys_in_use, keys);
716 
717  _field_size= table.field_size();
718 
719  setFields(_field_size + 1);
720  _fields[_field_size]= NULL;
721 
722  uint32_t local_null_fields= 0;
723  reclength= 0;
724 
725  std::vector<uint32_t> field_offsets;
726  std::vector<uint32_t> field_pack_length;
727 
728  field_offsets.resize(_field_size);
729  field_pack_length.resize(_field_size);
730 
731  uint32_t interval_count= 0;
732  uint32_t interval_parts= 0;
733 
734  uint32_t stored_columns_reclength= 0;
735 
736  for (unsigned int fieldnr= 0; fieldnr < _field_size; fieldnr++)
737  {
738  message::Table::Field pfield= table.field(fieldnr);
739  if (pfield.constraints().is_nullable()) // Historical reference
740  {
741  local_null_fields++;
742  }
743  else if (not pfield.constraints().is_notnull())
744  {
745  local_null_fields++;
746  }
747 
748  enum_field_types drizzle_field_type= proto_field_type_to_drizzle_type(pfield);
749 
750  field_offsets[fieldnr]= stored_columns_reclength;
751 
752  /* the below switch is very similar to
753  CreateField::create_length_to_internal_length in field.cc
754  (which should one day be replace by just this code)
755  */
756  switch(drizzle_field_type)
757  {
758  case DRIZZLE_TYPE_BLOB:
759  case DRIZZLE_TYPE_VARCHAR:
760  {
761  message::Table::Field::StringFieldOptions field_options= pfield.string_options();
762 
763  const charset_info_st *cs= get_charset(field_options.has_collation_id() ?
764  field_options.collation_id() : 0);
765 
766  if (! cs)
767  cs= default_charset_info;
768 
769  field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type,
770  field_options.length() * cs->mbmaxlen);
771  }
772  break;
773  case DRIZZLE_TYPE_ENUM:
774  {
775  message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
776 
777  field_pack_length[fieldnr]= 4;
778 
779  interval_count++;
780  interval_parts+= field_options.field_value_size();
781  }
782  break;
783  case DRIZZLE_TYPE_DECIMAL:
784  {
785  message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
786 
787  field_pack_length[fieldnr]= class_decimal_get_binary_size(fo.precision(), fo.scale());
788  }
789  break;
790  default:
791  /* Zero is okay here as length is fixed for other types. */
792  field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type, 0);
793  }
794 
795  reclength+= field_pack_length[fieldnr];
796  stored_columns_reclength+= field_pack_length[fieldnr];
797  }
798 
799  /* data_offset added to stored_rec_length later */
800  stored_rec_length= stored_columns_reclength;
801 
802  null_fields= local_null_fields;
803 
804  ulong null_bits= local_null_fields;
805  if (! table_options.pack_record())
806  null_bits++;
807  ulong data_offset= (null_bits + 7)/8;
808 
809 
810  reclength+= data_offset;
811  stored_rec_length+= data_offset;
812 
813  ulong local_rec_buff_length;
814 
815  local_rec_buff_length= ALIGN_SIZE(reclength + 1);
816  rec_buff_length= local_rec_buff_length;
817 
818  resizeDefaultValues(local_rec_buff_length);
819  unsigned char* record= getDefaultValues();
820  int null_count= 0;
821 
822  if (! table_options.pack_record())
823  {
824  null_count++; // one bit for delete mark.
825  *record|= 1;
826  }
827 
828 
829  intervals.resize(interval_count);
830 
831  /* Now fix the TYPELIBs for the intervals (enum values)
832  and field names.
833  */
834 
835  uint32_t interval_nr= 0;
836 
837  for (unsigned int fieldnr= 0; fieldnr < _field_size; fieldnr++)
838  {
839  message::Table::Field pfield= table.field(fieldnr);
840 
841  /* enum typelibs */
842  if (pfield.type() != message::Table::Field::ENUM)
843  continue;
844 
845  message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
846 
847  if (field_options.field_value_size() > Field_enum::max_supported_elements)
848  {
849  my_error(ER_CORRUPT_TABLE_DEFINITION_ENUM, MYF(0), table.name().c_str());
850 
851  return ER_CORRUPT_TABLE_DEFINITION_ENUM; // Historical
852  }
853 
854 
855  const charset_info_st *charset= get_charset(field_options.has_collation_id() ?
856  field_options.collation_id() : 0);
857 
858  if (! charset)
859  charset= default_charset_info;
860 
861  TYPELIB *t= (&intervals[interval_nr]);
862 
863  t->type_names= (const char**)mem().alloc((field_options.field_value_size() + 1) * sizeof(char*));
864  t->type_lengths= (unsigned int*)mem().alloc((field_options.field_value_size() + 1) * sizeof(unsigned int));
865 
866  t->type_names[field_options.field_value_size()]= NULL;
867  t->type_lengths[field_options.field_value_size()]= 0;
868 
869  t->count= field_options.field_value_size();
870  t->name= NULL;
871 
872  for (int n= 0; n < field_options.field_value_size(); n++)
873  {
874  t->type_names[n]= mem().strdup(field_options.field_value(n));
875 
876  /*
877  * Go ask the charset what the length is as for "" length=1
878  * and there's stripping spaces or some other crack going on.
879  */
880  t->type_lengths[n]= charset->cset->lengthsp(charset, t->type_names[n], field_options.field_value(n).length());
881  }
882  interval_nr++;
883  }
884 
885 
886  /* and read the fields */
887  interval_nr= 0;
888 
889  bool use_hash= _field_size >= MAX_FIELDS_BEFORE_HASH;
890 
891  unsigned char* null_pos= getDefaultValues();
892  int null_bit_pos= (table_options.pack_record()) ? 0 : 1;
893 
894  for (unsigned int fieldnr= 0; fieldnr < _field_size; fieldnr++)
895  {
896  message::Table::Field pfield= table.field(fieldnr);
897 
898  Field::utype unireg_type= Field::NONE;
899 
900  if (pfield.has_numeric_options() &&
901  pfield.numeric_options().is_autoincrement())
902  {
903  unireg_type= Field::NEXT_NUMBER;
904  }
905 
906  if (pfield.has_options() &&
907  pfield.options().has_default_expression() &&
908  pfield.options().default_expression().compare("CURRENT_TIMESTAMP") == 0)
909  {
910  if (pfield.options().has_update_expression() &&
911  pfield.options().update_expression().compare("CURRENT_TIMESTAMP") == 0)
912  {
913  unireg_type= Field::TIMESTAMP_DNUN_FIELD;
914  }
915  else if (! pfield.options().has_update_expression())
916  {
917  unireg_type= Field::TIMESTAMP_DN_FIELD;
918  }
919  else
920  {
921  assert(0); // Invalid update value.
922  abort();
923  }
924  }
925  else if (pfield.has_options() &&
926  pfield.options().has_update_expression() &&
927  pfield.options().update_expression().compare("CURRENT_TIMESTAMP") == 0)
928  {
929  unireg_type= Field::TIMESTAMP_UN_FIELD;
930  }
931 
932  str_ref comment;
933  if (pfield.has_comment())
934  {
935  comment.assign(mem().strdup(pfield.comment()), pfield.comment().size());
936  }
937 
938  enum_field_types field_type;
939 
940  field_type= proto_field_type_to_drizzle_type(pfield);
941 
942  const charset_info_st *charset= &my_charset_bin;
943 
944  if (field_type == DRIZZLE_TYPE_BLOB || field_type == DRIZZLE_TYPE_VARCHAR)
945  {
946  message::Table::Field::StringFieldOptions field_options= pfield.string_options();
947 
948  charset= get_charset(field_options.has_collation_id() ? field_options.collation_id() : 0);
949 
950  if (not charset)
951  charset= default_charset_info;
952  }
953 
954  if (field_type == DRIZZLE_TYPE_ENUM)
955  {
956  message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
957 
958  charset= get_charset(field_options.has_collation_id() ? field_options.collation_id() : 0);
959 
960  if (not charset)
961  charset= default_charset_info;
962  }
963 
964  uint8_t decimals= 0;
965  if (field_type == DRIZZLE_TYPE_DECIMAL || field_type == DRIZZLE_TYPE_DOUBLE)
966  {
967  message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
968 
969  if (not pfield.has_numeric_options() || ! fo.has_scale())
970  {
971  /*
972  We don't write the default to table proto so
973  if no decimals specified for DOUBLE, we use the default.
974  */
975  decimals= NOT_FIXED_DEC;
976  }
977  else
978  {
979  if (fo.scale() > DECIMAL_MAX_SCALE)
980  {
981  local_error= ER_NOT_FORM_FILE;
982 
983  return true;
984  }
985  decimals= static_cast<uint8_t>(fo.scale());
986  }
987  }
988 
989  Item *default_value= NULL;
990 
991  if (pfield.options().has_default_value() ||
992  pfield.options().default_null() ||
993  pfield.options().has_default_bin_value())
994  {
995  default_value= default_value_item(field_type, *charset, pfield.options().default_null(), pfield.options().default_value(), pfield.options().default_bin_value());
996  if (default_value == NULL)
997  {
998  my_error(ER_INVALID_DEFAULT, MYF(0), pfield.name().c_str());
999  return true;
1000  }
1001  }
1002 
1003 
1004  uint32_t field_length= 0; //Assignment is for compiler complaint.
1005 
1006  // We set field_length in this loop.
1007  switch (field_type)
1008  {
1009  case DRIZZLE_TYPE_BLOB:
1010  case DRIZZLE_TYPE_VARCHAR:
1011  {
1012  message::Table::Field::StringFieldOptions field_options= pfield.string_options();
1013 
1014  charset= get_charset(field_options.has_collation_id() ?
1015  field_options.collation_id() : 0);
1016 
1017  if (! charset)
1018  charset= default_charset_info;
1019 
1020  field_length= field_options.length() * charset->mbmaxlen;
1021  }
1022  break;
1023  case DRIZZLE_TYPE_DOUBLE:
1024  {
1025  message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
1026  if (!fo.has_precision() && !fo.has_scale())
1027  {
1028  field_length= DBL_DIG+7;
1029  }
1030  else
1031  {
1032  field_length= fo.precision();
1033  }
1034  if (field_length < decimals &&
1035  decimals != NOT_FIXED_DEC)
1036  {
1037  my_error(ER_M_BIGGER_THAN_D, MYF(0), pfield.name().c_str());
1038  local_error= ER_M_BIGGER_THAN_D;
1039  return true;
1040  }
1041  break;
1042  }
1043  case DRIZZLE_TYPE_DECIMAL:
1044  {
1045  message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
1046 
1047  field_length= class_decimal_precision_to_length(fo.precision(), fo.scale(),
1048  false);
1049  break;
1050  }
1051  case DRIZZLE_TYPE_DATETIME:
1052  field_length= DateTime::MAX_STRING_LENGTH;
1053  break;
1054  case DRIZZLE_TYPE_DATE:
1055  field_length= Date::MAX_STRING_LENGTH;
1056  break;
1057  case DRIZZLE_TYPE_ENUM:
1058  {
1059  field_length= 0;
1060 
1061  message::Table::Field::EnumerationValues fo= pfield.enumeration_values();
1062 
1063  for (int valnr= 0; valnr < fo.field_value_size(); valnr++)
1064  {
1065  if (fo.field_value(valnr).length() > field_length)
1066  {
1067  field_length= charset->cset->numchars(charset,
1068  fo.field_value(valnr).c_str(),
1069  fo.field_value(valnr).c_str()
1070  + fo.field_value(valnr).length())
1071  * charset->mbmaxlen;
1072  }
1073  }
1074  }
1075  break;
1076  case DRIZZLE_TYPE_LONG:
1077  {
1078  uint32_t sign_len= pfield.constraints().is_unsigned() ? 0 : 1;
1079  field_length= MAX_INT_WIDTH+sign_len;
1080  }
1081  break;
1082  case DRIZZLE_TYPE_LONGLONG:
1083  {
1084  uint32_t sign_len= pfield.constraints().is_unsigned() ? 0 : 1;
1085  field_length= MAX_BIGINT_WIDTH+sign_len;
1086  }
1087  break;
1088  case DRIZZLE_TYPE_UUID:
1089  field_length= field::Uuid::max_string_length();
1090  break;
1091  case DRIZZLE_TYPE_IPV6:
1092  field_length= field::IPv6::max_string_length();
1093  break;
1094  case DRIZZLE_TYPE_BOOLEAN:
1095  field_length= field::Boolean::max_string_length();
1096  break;
1097  case DRIZZLE_TYPE_MICROTIME:
1098  field_length= field::Microtime::max_string_length();
1099  break;
1100  case DRIZZLE_TYPE_TIMESTAMP:
1101  field_length= field::Epoch::max_string_length();
1102  break;
1103  case DRIZZLE_TYPE_TIME:
1104  field_length= field::Time::max_string_length();
1105  break;
1106  case DRIZZLE_TYPE_NULL:
1107  abort(); // Programming error
1108  }
1109 
1110  bool is_not_null= false;
1111 
1112  if (not pfield.constraints().is_nullable())
1113  {
1114  is_not_null= true;
1115  }
1116  else if (pfield.constraints().is_notnull())
1117  {
1118  is_not_null= true;
1119  }
1120 
1121  Field* f= make_field(pfield,
1122  record + field_offsets[fieldnr] + data_offset,
1123  field_length,
1124  not is_not_null,
1125  null_pos,
1126  null_bit_pos,
1127  decimals,
1128  field_type,
1129  charset,
1130  MTYP_TYPENR(unireg_type),
1131  ((field_type == DRIZZLE_TYPE_ENUM) ? &intervals[interval_nr++] : (TYPELIB*) 0),
1132  getTableMessage()->field(fieldnr).name().c_str());
1133 
1134  _fields[fieldnr]= f;
1135 
1136  // Insert post make_field code here.
1137  switch (field_type)
1138  {
1139  case DRIZZLE_TYPE_BLOB:
1140  case DRIZZLE_TYPE_VARCHAR:
1141  case DRIZZLE_TYPE_DOUBLE:
1142  case DRIZZLE_TYPE_DECIMAL:
1143  case DRIZZLE_TYPE_TIMESTAMP:
1144  case DRIZZLE_TYPE_TIME:
1145  case DRIZZLE_TYPE_DATETIME:
1146  case DRIZZLE_TYPE_MICROTIME:
1147  case DRIZZLE_TYPE_DATE:
1148  case DRIZZLE_TYPE_ENUM:
1149  case DRIZZLE_TYPE_LONG:
1150  case DRIZZLE_TYPE_LONGLONG:
1151  case DRIZZLE_TYPE_NULL:
1152  case DRIZZLE_TYPE_UUID:
1153  case DRIZZLE_TYPE_IPV6:
1154  case DRIZZLE_TYPE_BOOLEAN:
1155  break;
1156  }
1157 
1158  // This needs to go, we should be setting the "use" on the field so that
1159  // it does not reference the share/table.
1160  table::Shell temp_table(*this); /* Use this so that BLOB DEFAULT '' works */
1161  temp_table.in_use= &session;
1162 
1163  f->init(&temp_table); /* blob default values need table obj */
1164 
1165  if (! (f->flags & NOT_NULL_FLAG))
1166  {
1167  *f->null_ptr|= f->null_bit;
1168  if (! (null_bit_pos= (null_bit_pos + 1) & 7)) /* @TODO Ugh. */
1169  null_pos++;
1170  null_count++;
1171  }
1172 
1173  if (default_value)
1174  {
1175  enum_check_fields old_count_cuted_fields= session.count_cuted_fields;
1176  session.count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
1177  int res= default_value->save_in_field(f, 1);
1178  session.count_cuted_fields= old_count_cuted_fields;
1179  if (res != 0 && res != 3) /* @TODO Huh? */
1180  {
1181  my_error(ER_INVALID_DEFAULT, MYF(0), f->field_name);
1182  local_error= ER_INVALID_DEFAULT;
1183 
1184  return true;
1185  }
1186  }
1187  else if (f->real_type() == DRIZZLE_TYPE_ENUM && (f->flags & NOT_NULL_FLAG))
1188  {
1189  f->set_notnull();
1190  f->store((int64_t) 1, true);
1191  }
1192  else
1193  {
1194  f->reset();
1195  }
1196 
1197  /* hack to undo f->init() */
1198  f->setTable(NULL);
1199  f->orig_table= NULL;
1200 
1201  f->setPosition(fieldnr);
1202  f->comment= comment;
1203  if (not default_value &&
1204  not (f->unireg_check==Field::NEXT_NUMBER) &&
1205  (f->flags & NOT_NULL_FLAG) &&
1206  (not f->is_timestamp()))
1207  {
1208  f->flags|= NO_DEFAULT_VALUE_FLAG;
1209  }
1210 
1211  if (f->unireg_check == Field::NEXT_NUMBER)
1212  found_next_number_field= &(_fields[fieldnr]);
1213 
1214  if (use_hash) /* supposedly this never fails... but comments lie */
1215  {
1216  const char *local_field_name= _fields[fieldnr]->field_name;
1217  name_hash.insert(make_pair(local_field_name, &(_fields[fieldnr])));
1218  }
1219  }
1220 
1221  keyinfo= key_info;
1222  for (unsigned int keynr= 0; keynr < keys; keynr++, keyinfo++)
1223  {
1224  key_part= keyinfo->key_part;
1225 
1226  for (unsigned int partnr= 0;
1227  partnr < keyinfo->key_parts;
1228  partnr++, key_part++)
1229  {
1230  /*
1231  * Fix up key_part->offset by adding data_offset.
1232  * We really should compute offset as well.
1233  * But at least this way we are a little better.
1234  */
1235  key_part->offset= field_offsets[key_part->fieldnr-1] + data_offset;
1236  }
1237  }
1238 
1239  /*
1240  We need to set the unused bits to 1. If the number of bits is a multiple
1241  of 8 there are no unused bits.
1242  */
1243  if (null_count & 7)
1244  *(record + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
1245 
1246  null_bytes= (null_pos - (unsigned char*) record + (null_bit_pos + 7) / 8);
1247 
1248  last_null_bit_pos= null_bit_pos;
1249 
1250  /* Fix key stuff */
1251  if (key_parts)
1252  {
1253  uint32_t local_primary_key= doesKeyNameExist("PRIMARY");
1254  keyinfo= key_info;
1255  key_part= keyinfo->key_part;
1256 
1257  for (uint32_t key= 0; key < keys; key++,keyinfo++)
1258  {
1259  uint32_t usable_parts= 0;
1260 
1261  if (local_primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
1262  {
1263  /*
1264  If the UNIQUE key doesn't have NULL columns and is not a part key
1265  declare this as a primary key.
1266  */
1267  local_primary_key=key;
1268  for (uint32_t i= 0; i < keyinfo->key_parts; i++)
1269  {
1270  uint32_t fieldnr= key_part[i].fieldnr;
1271  if (not fieldnr ||
1272  _fields[fieldnr-1]->null_ptr ||
1273  _fields[fieldnr-1]->key_length() != key_part[i].length)
1274  {
1275  local_primary_key= MAX_KEY; // Can't be used
1276  break;
1277  }
1278  }
1279  }
1280 
1281  for (uint32_t i= 0 ; i < keyinfo->key_parts ; key_part++,i++)
1282  {
1283  Field *local_field;
1284  if (! key_part->fieldnr)
1285  {
1286  return ENOMEM;
1287  }
1288  local_field= key_part->field= _fields[key_part->fieldnr-1];
1289  key_part->type= local_field->key_type();
1290  if (local_field->null_ptr)
1291  {
1292  key_part->null_offset=(uint32_t) ((unsigned char*) local_field->null_ptr - getDefaultValues());
1293  key_part->null_bit= local_field->null_bit;
1294  key_part->store_length+=HA_KEY_NULL_LENGTH;
1295  keyinfo->flags|=HA_NULL_PART_KEY;
1296  keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
1297  keyinfo->key_length+= HA_KEY_NULL_LENGTH;
1298  }
1299  if (local_field->type() == DRIZZLE_TYPE_BLOB ||
1300  local_field->real_type() == DRIZZLE_TYPE_VARCHAR)
1301  {
1302  if (local_field->type() == DRIZZLE_TYPE_BLOB)
1303  key_part->key_part_flag|= HA_BLOB_PART;
1304  else
1305  key_part->key_part_flag|= HA_VAR_LENGTH_PART;
1306  keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
1307  key_part->store_length+=HA_KEY_BLOB_LENGTH;
1308  keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
1309  }
1310  if (i == 0 && key != local_primary_key)
1311  local_field->flags |= (((keyinfo->flags & HA_NOSAME) &&
1312  (keyinfo->key_parts == 1)) ?
1313  UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
1314  if (i == 0)
1315  local_field->key_start.set(key);
1316  if (local_field->key_length() == key_part->length &&
1317  !(local_field->flags & BLOB_FLAG))
1318  {
1319  enum ha_key_alg algo= key_info[key].algorithm;
1320  if (db_type()->index_flags(algo) & HA_KEYREAD_ONLY)
1321  {
1322  keys_for_keyread.set(key);
1323  local_field->part_of_key.set(key);
1324  local_field->part_of_key_not_clustered.set(key);
1325  }
1326  if (db_type()->index_flags(algo) & HA_READ_ORDER)
1327  local_field->part_of_sortkey.set(key);
1328  }
1329  if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
1330  usable_parts == i)
1331  usable_parts++; // For FILESORT
1332  local_field->flags|= PART_KEY_FLAG;
1333  if (key == local_primary_key)
1334  {
1335  local_field->flags|= PRI_KEY_FLAG;
1336  /*
1337  If this field is part of the primary key and all keys contains
1338  the primary key, then we can use any key to find this column
1339  */
1340  if (storage_engine->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX))
1341  {
1342  local_field->part_of_key= keys_in_use;
1343  if (local_field->part_of_sortkey.test(key))
1344  local_field->part_of_sortkey= keys_in_use;
1345  }
1346  }
1347  if (local_field->key_length() != key_part->length)
1348  {
1349  key_part->key_part_flag|= HA_PART_KEY_SEG;
1350  }
1351  }
1352  keyinfo->usable_key_parts= usable_parts; // Filesort
1353 
1354  set_if_bigger(max_key_length,keyinfo->key_length+
1355  keyinfo->key_parts);
1356  total_key_length+= keyinfo->key_length;
1357 
1358  if (keyinfo->flags & HA_NOSAME)
1359  {
1360  set_if_bigger(max_unique_length,keyinfo->key_length);
1361  }
1362  }
1363  if (local_primary_key < MAX_KEY &&
1364  (keys_in_use.test(local_primary_key)))
1365  {
1366  primary_key= local_primary_key;
1367  /*
1368  If we are using an integer as the primary key then allow the user to
1369  refer to it as '_rowid'
1370  */
1371  if (key_info[local_primary_key].key_parts == 1)
1372  {
1373  Field *local_field= key_info[local_primary_key].key_part[0].field;
1374  if (local_field && local_field->result_type() == INT_RESULT)
1375  {
1376  /* note that fieldnr here (and rowid_field_offset) starts from 1 */
1377  rowid_field_offset= (key_info[local_primary_key].key_part[0].
1378  fieldnr);
1379  }
1380  }
1381  }
1382  }
1383 
1384  if (found_next_number_field)
1385  {
1386  Field *reg_field= *found_next_number_field;
1387  if ((int) (next_number_index= (uint32_t)
1388  find_ref_key(key_info, keys,
1389  getDefaultValues(), reg_field,
1390  &next_number_key_offset,
1391  &next_number_keypart)) < 0)
1392  {
1393  /* Wrong field definition */
1394  local_error= ER_NOT_FORM_FILE;
1395 
1396  return true;
1397  }
1398  else
1399  {
1400  reg_field->flags |= AUTO_INCREMENT_FLAG;
1401  }
1402  }
1403 
1404  if (blob_fields)
1405  {
1406  /* Store offsets to blob fields to find them fast */
1407  blob_field.resize(blob_fields);
1408  uint32_t *save= &blob_field[0];
1409  uint32_t k= 0;
1410  for (Fields::iterator iter= _fields.begin(); iter != _fields.end()-1; iter++, k++)
1411  {
1412  if ((*iter)->flags & BLOB_FLAG)
1413  (*save++)= k;
1414  }
1415  }
1416 
1417  all_set.clear();
1418  all_set.resize(_field_size);
1419  all_set.set();
1420 
1421  return local_error != EE_OK;
1422 }
1423 
1424 /*
1425  Read table definition from a binary / text based .frm cursor
1426 
1427  SYNOPSIS
1428  open_table_def()
1429  session Thread Cursor
1430  share Fill this with table definition
1431 
1432  NOTES
1433  This function is called when the table definition is not cached in
1434  definition::Cache::getCache()
1435  The data is returned in 'share', which is alloced by
1436  alloc_table_share().. The code assumes that share is initialized.
1437 
1438  RETURN VALUES
1439  0 ok
1440  1 Error (see open_table_error)
1441  2 Error (see open_table_error)
1442  3 Wrong data in .frm cursor
1443  4 Error (see open_table_error)
1444  5 Error (see open_table_error: charset unavailable)
1445  6 Unknown .frm version
1446 */
1447 
1448 int TableShare::open_table_def(Session& session, const identifier::Table &identifier)
1449 {
1450  drizzled::error_t local_error= EE_OK;
1451 
1452  message::table::shared_ptr table= plugin::StorageEngine::getTableMessage(session, identifier, local_error);
1453 
1454  if (table and table->IsInitialized())
1455  {
1456  if (parse_table_proto(session, *table))
1457  {
1458  local_error= ER_CORRUPT_TABLE_DEFINITION_UNKNOWN;
1459  my_error(ER_CORRUPT_TABLE_DEFINITION_UNKNOWN, identifier);
1460  }
1461  else
1462  {
1463  setTableCategory(TABLE_CATEGORY_USER);
1464  local_error= EE_OK;
1465  }
1466  }
1467  else if (table and not table->IsInitialized())
1468  {
1469  local_error= ER_CORRUPT_TABLE_DEFINITION_UNKNOWN;
1470  my_error(ER_CORRUPT_TABLE_DEFINITION_UNKNOWN, identifier);
1471  }
1472  else
1473  {
1474  local_error= ER_TABLE_UNKNOWN;
1475  my_error(ER_TABLE_UNKNOWN, identifier);
1476  }
1477 
1478  return static_cast<int>(local_error);
1479 }
1480 
1481 
1482 /*
1483  Open a table based on a TableShare
1484 
1485  SYNOPSIS
1486  open_table_from_share()
1487  session Thread Cursor
1488  share Table definition
1489  alias Alias for table
1490  db_stat open flags (for example HA_OPEN_KEYFILE|
1491  HA_OPEN_RNDFILE..) can be 0 (example in
1492  ha_example_table)
1493  ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
1494  outparam result table
1495 
1496  RETURN VALUES
1497  0 ok
1498  1 Error (see open_table_error)
1499  2 Error (see open_table_error)
1500  3 Wrong data in .frm cursor
1501  4 Error (see open_table_error)
1502  5 Error (see open_table_error: charset unavailable)
1503  7 Table definition has changed in engine
1504 */
1505 int TableShare::open_table_from_share(Session *session,
1506  const identifier::Table &identifier,
1507  const char *alias,
1508  uint32_t db_stat, uint32_t ha_open_flags,
1509  Table &outparam)
1510 {
1511  bool error_reported= false;
1512  int ret= open_table_from_share_inner(session, alias, db_stat, outparam);
1513 
1514  if (not ret)
1515  ret= open_table_cursor_inner(identifier, db_stat, ha_open_flags, outparam, error_reported);
1516 
1517  if (not ret)
1518  return ret;
1519 
1520  if (not error_reported)
1521  open_table_error(ret, errno, 0);
1522 
1523  boost::checked_delete(outparam.cursor);
1524  outparam.cursor= 0; // For easier error checking
1525  outparam.db_stat= 0;
1526  outparam.mem().free_root(MYF(0)); // Safe to call on zeroed root
1527  outparam.clearAlias();
1528 
1529  return ret;
1530 }
1531 
1532 int TableShare::open_table_from_share_inner(Session *session, const char *alias, uint32_t db_stat, Table &outparam)
1533 {
1534  int local_error= 1;
1535  outparam.resetTable(session, this, db_stat);
1536 
1537  outparam.setAlias(alias);
1538 
1539  /* Allocate Cursor */
1540  if (not (outparam.cursor= db_type()->getCursor(outparam)))
1541  return local_error;
1542 
1543  local_error= 4;
1544  uint32_t records= 0;
1545  if (db_stat & HA_OPEN_KEYFILE)
1546  records=1;
1547 
1548  records++;
1549 
1550  unsigned char* record= outparam.alloc(rec_buff_length * records);
1551 
1552  if (records == 0)
1553  {
1554  /* We are probably in hard repair, and the buffers should not be used */
1555  outparam.record[0]= outparam.record[1]= getDefaultValues();
1556  }
1557  else
1558  {
1559  outparam.record[0]= record;
1560  if (records > 1)
1561  outparam.record[1]= record+ rec_buff_length;
1562  else
1563  outparam.record[1]= outparam.getInsertRecord(); // Safety
1564  }
1565 
1566 #ifdef HAVE_VALGRIND
1567  /*
1568  We need this because when we read var-length rows, we are not updating
1569  bytes after end of varchar
1570  */
1571  if (records > 1)
1572  {
1573  memcpy(outparam.getInsertRecord(), getDefaultValues(), rec_buff_length);
1574  memcpy(outparam.getUpdateRecord(), getDefaultValues(), null_bytes);
1575  if (records > 2)
1576  memcpy(outparam.getUpdateRecord(), getDefaultValues(), rec_buff_length);
1577  }
1578 #endif
1579  if (records > 1)
1580  {
1581  memcpy(outparam.getUpdateRecord(), getDefaultValues(), null_bytes);
1582  }
1583 
1584  Field** field_ptr = new (outparam.mem()) Field*[_field_size + 1];
1585 
1586  outparam.setFields(field_ptr);
1587 
1588  record= outparam.getInsertRecord()-1; /* Fieldstart = 1 */
1589 
1590  outparam.null_flags= (unsigned char*) record+1;
1591 
1592  /* Setup copy of fields from share, but use the right alias and record */
1593  for (uint32_t i= 0 ; i < _field_size; i++, field_ptr++)
1594  {
1595  if (!((*field_ptr)= _fields[i]->clone(&outparam.mem(), &outparam)))
1596  return local_error;
1597  }
1598  *field_ptr= 0; // End marker
1599 
1600  if (found_next_number_field)
1601  outparam.found_next_number_field=
1602  outparam.getField(positionFields(found_next_number_field));
1603  if (timestamp_field)
1604  outparam.timestamp_field= (field::Epoch*) outparam.getField(timestamp_field->position());
1605 
1606  /* Fix key->name and key_part->field */
1607  if (key_parts)
1608  {
1609  uint32_t n_length= keys * sizeof(KeyInfo) + key_parts * sizeof(KeyPartInfo);
1610  KeyInfo* local_key_info= (KeyInfo*) outparam.alloc(n_length);
1611  outparam.key_info= local_key_info;
1612  KeyPartInfo* key_part= reinterpret_cast<KeyPartInfo*>(local_key_info+keys);
1613 
1614  memcpy(local_key_info, key_info, sizeof(*local_key_info)*keys);
1615  memcpy(key_part, key_info[0].key_part, sizeof(*key_part) * key_parts);
1616 
1617  for (KeyInfo* key_info_end= local_key_info + keys; local_key_info < key_info_end; local_key_info++)
1618  {
1619  local_key_info->table= &outparam;
1620  local_key_info->key_part= key_part;
1621 
1622  for (KeyPartInfo* key_part_end= key_part+ local_key_info->key_parts; key_part < key_part_end; key_part++)
1623  {
1624  Field *local_field= key_part->field= outparam.getField(key_part->fieldnr-1);
1625 
1626  if (local_field->key_length() != key_part->length && not (local_field->flags & BLOB_FLAG))
1627  {
1628  /*
1629  We are using only a prefix of the column as a key:
1630  Create a new field for the key part that matches the index
1631  */
1632  local_field= key_part->field= local_field->new_field(&outparam.mem(), &outparam, 0);
1633  local_field->field_length= key_part->length;
1634  }
1635  }
1636  }
1637  }
1638 
1639  /* Allocate bitmaps */
1640 
1641  outparam.def_read_set.resize(_field_size);
1642  outparam.def_write_set.resize(_field_size);
1643  outparam.tmp_set.resize(_field_size);
1644  outparam.default_column_bitmaps();
1645 
1646  return 0;
1647 }
1648 
1649 int TableShare::open_table_cursor_inner(const identifier::Table &identifier,
1650  uint32_t db_stat, uint32_t ha_open_flags,
1651  Table &outparam,
1652  bool &error_reported)
1653 {
1654  /* The table struct is now initialized; Open the table */
1655  int local_error= 2;
1656  if (db_stat)
1657  {
1658  assert(!(db_stat & HA_WAIT_IF_LOCKED));
1659  int ha_err;
1660 
1661  if ((ha_err= (outparam.cursor->ha_open(identifier,
1662  (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
1663  (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE : HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
1664  {
1665  switch (ha_err)
1666  {
1667  case HA_ERR_NO_SUCH_TABLE:
1668  /*
1669  The table did not exists in storage engine, use same error message
1670  as if the .frm cursor didn't exist
1671  */
1672  local_error= 1;
1673  errno= ENOENT;
1674  break;
1675  case EMFILE:
1676  /*
1677  Too many files opened, use same error message as if the .frm
1678  cursor can't open
1679  */
1680  local_error= 1;
1681  errno= EMFILE;
1682  break;
1683  default:
1684  outparam.print_error(ha_err, MYF(0));
1685  error_reported= true;
1686  if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
1687  local_error= 7;
1688  break;
1689  }
1690  return local_error;
1691  }
1692  }
1693 
1694  return 0;
1695 }
1696 
1697 /* error message when opening a form cursor */
1698 void TableShare::open_table_error(int pass_error, int db_errno, int pass_errarg)
1699 {
1700  char buff[FN_REFLEN];
1701  myf errortype= ME_ERROR+ME_WAITTANG;
1702 
1703  switch (pass_error) {
1704  case 7:
1705  case 1:
1706  if (db_errno == ENOENT)
1707  {
1708  identifier::Table identifier(db.data(), table_name.data());
1709  my_error(ER_TABLE_UNKNOWN, identifier);
1710  }
1711  else
1712  {
1713  snprintf(buff, sizeof(buff), "%s",normalized_path.data());
1714  my_error((db_errno == EMFILE) ? ER_CANT_OPEN_FILE : ER_FILE_NOT_FOUND, errortype, buff, db_errno);
1715  }
1716  break;
1717  case 2:
1718  {
1719  drizzled::error_t err_no= (db_errno == ENOENT) ? ER_FILE_NOT_FOUND : (db_errno == EAGAIN) ? ER_FILE_USED : ER_CANT_OPEN_FILE;
1720  my_error(err_no, errortype, normalized_path.data(), db_errno);
1721  break;
1722  }
1723  case 5:
1724  {
1725  const char *csname= get_charset_name((uint32_t) pass_errarg);
1726  char tmp[10];
1727  if (!csname || csname[0] =='?')
1728  {
1729  snprintf(tmp, sizeof(tmp), "#%d", pass_errarg);
1730  csname= tmp;
1731  }
1732  my_printf_error(ER_UNKNOWN_COLLATION, _("Unknown collation '%s' in table '%-.64s' definition"), MYF(0), csname, table_name.data());
1733  break;
1734  }
1735  case 6:
1736  snprintf(buff, sizeof(buff), "%s", normalized_path.data());
1737  my_printf_error(ER_NOT_FORM_FILE, _("Table '%-.64s' was created with a different version of Drizzle and cannot be read"), MYF(0), buff);
1738  break;
1739  case 8:
1740  break;
1741  default: /* Better wrong error than none */
1742  case 4:
1743  snprintf(buff, sizeof(buff), "%s", normalized_path.data());
1744  my_error(ER_NOT_FORM_FILE, errortype, buff, 0);
1745  break;
1746  }
1747  return;
1748 } /* open_table_error */
1749 
1750 Field *TableShare::make_field(const message::Table::Field &pfield,
1751  unsigned char *ptr,
1752  uint32_t field_length,
1753  bool is_nullable,
1754  unsigned char *null_pos,
1755  unsigned char null_bit,
1756  uint8_t decimals,
1757  enum_field_types field_type,
1758  const charset_info_st * field_charset,
1759  Field::utype unireg_check,
1760  TYPELIB *interval,
1761  const char *field_name)
1762 {
1763  return make_field(pfield,
1764  ptr,
1765  field_length,
1766  is_nullable,
1767  null_pos,
1768  null_bit,
1769  decimals,
1770  field_type,
1771  field_charset,
1772  unireg_check,
1773  interval,
1774  field_name,
1775  pfield.constraints().is_unsigned());
1776 }
1777 
1778 Field *TableShare::make_field(const message::Table::Field &,
1779  unsigned char *ptr,
1780  uint32_t field_length,
1781  bool is_nullable,
1782  unsigned char *null_pos,
1783  unsigned char null_bit,
1784  uint8_t decimals,
1785  enum_field_types field_type,
1786  const charset_info_st * field_charset,
1787  Field::utype unireg_check,
1788  TYPELIB *interval,
1789  const char *field_name,
1790  bool is_unsigned)
1791 {
1792  if (! is_nullable)
1793  {
1794  null_pos=0;
1795  null_bit=0;
1796  }
1797  else
1798  {
1799  null_bit= ((unsigned char) 1) << null_bit;
1800  }
1801 
1802  switch (field_type)
1803  {
1804  case DRIZZLE_TYPE_ENUM:
1805  return new (&mem_root) Field_enum(ptr,
1806  field_length,
1807  null_pos,
1808  null_bit,
1809  field_name,
1810  interval,
1811  field_charset);
1812  case DRIZZLE_TYPE_VARCHAR:
1813  setVariableWidth();
1814  return new (&mem_root) Field_varstring(ptr,field_length,
1815  ha_varchar_packlength(field_length),
1816  null_pos,null_bit,
1817  field_name,
1818  field_charset);
1819  case DRIZZLE_TYPE_BLOB:
1820  return new (&mem_root) Field_blob(ptr,
1821  null_pos,
1822  null_bit,
1823  field_name,
1824  this,
1825  field_charset);
1826  case DRIZZLE_TYPE_DECIMAL:
1827  return new (&mem_root) Field_decimal(ptr,
1828  field_length,
1829  null_pos,
1830  null_bit,
1831  unireg_check,
1832  field_name,
1833  decimals);
1834  case DRIZZLE_TYPE_DOUBLE:
1835  return new (&mem_root) Field_double(ptr,
1836  field_length,
1837  null_pos,
1838  null_bit,
1839  unireg_check,
1840  field_name,
1841  decimals,
1842  false,
1843  false /* is_unsigned */);
1844  case DRIZZLE_TYPE_UUID:
1845  return new (&mem_root) field::Uuid(ptr,
1846  field_length,
1847  null_pos,
1848  null_bit,
1849  field_name);
1850  case DRIZZLE_TYPE_IPV6:
1851  return new (&mem_root) field::IPv6(ptr,
1852  field_length,
1853  null_pos,
1854  null_bit,
1855  field_name);
1856  case DRIZZLE_TYPE_BOOLEAN:
1857  return new (&mem_root) field::Boolean(ptr,
1858  field_length,
1859  null_pos,
1860  null_bit,
1861  field_name,
1862  is_unsigned);
1863  case DRIZZLE_TYPE_LONG:
1864  return new (&mem_root) field::Int32(ptr,
1865  field_length,
1866  null_pos,
1867  null_bit,
1868  unireg_check,
1869  field_name);
1870  case DRIZZLE_TYPE_LONGLONG:
1871  {
1872  if (is_unsigned)
1873  {
1874  return new (&mem_root) field::Size(ptr,
1875  field_length,
1876  null_pos,
1877  null_bit,
1878  unireg_check,
1879  field_name);
1880  }
1881 
1882  return new (&mem_root) field::Int64(ptr,
1883  field_length,
1884  null_pos,
1885  null_bit,
1886  unireg_check,
1887  field_name);
1888  }
1889  case DRIZZLE_TYPE_MICROTIME:
1890  return new (&mem_root) field::Microtime(ptr,
1891  null_pos,
1892  null_bit,
1893  unireg_check,
1894  field_name,
1895  this);
1896  case DRIZZLE_TYPE_TIMESTAMP:
1897  return new (&mem_root) field::Epoch(ptr,
1898  null_pos,
1899  null_bit,
1900  unireg_check,
1901  field_name,
1902  this);
1903  case DRIZZLE_TYPE_TIME:
1904  return new (&mem_root) field::Time(ptr, field_length, null_pos, null_bit, field_name);
1905  case DRIZZLE_TYPE_DATE:
1906  return new (&mem_root) Field_date(ptr, null_pos, null_bit, field_name);
1907  case DRIZZLE_TYPE_DATETIME:
1908  return new (&mem_root) Field_datetime(ptr, null_pos, null_bit, field_name);
1909  case DRIZZLE_TYPE_NULL:
1910  return new (&mem_root) Field_null(ptr, field_length, field_name);
1911  }
1912  assert(false);
1913  abort();
1914 }
1915 
1916 void TableShare::refreshVersion()
1917 {
1918  version= g_refresh_version;
1919 }
1920 
1921 
1922 } /* namespace drizzled */