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