Drizzled Public API Documentation

base.cc
00001 /* -*- mode: c++; c-basic-offset: 2; i/dent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2010 Brian Aker
00005  *  Copyright (C) 2009 Sun Microsystems, Inc.
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 2 of the License, or
00010  *  (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with this program; if not, write to the Free Software
00019  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00022 /*
00023   This class is shared between different table objects. There is one
00024   instance of table share per one table in the database.
00025 */
00026 
00027 /* Basic functions needed by many modules */
00028 #include <config.h>
00029 
00030 #include <pthread.h>
00031 #include <float.h>
00032 
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <fcntl.h>
00036 
00037 
00038 #include <cassert>
00039 
00040 #include <drizzled/error.h>
00041 #include <drizzled/gettext.h>
00042 #include <drizzled/sql_base.h>
00043 #include <drizzled/pthread_globals.h>
00044 #include <drizzled/internal/my_pthread.h>
00045 
00046 #include <drizzled/table.h>
00047 #include <drizzled/table/shell.h>
00048 
00049 #include <drizzled/session.h>
00050 
00051 #include <drizzled/charset.h>
00052 #include <drizzled/internal/m_string.h>
00053 #include <drizzled/internal/my_sys.h>
00054 
00055 #include <drizzled/item/string.h>
00056 #include <drizzled/item/int.h>
00057 #include <drizzled/item/decimal.h>
00058 #include <drizzled/item/float.h>
00059 #include <drizzled/item/null.h>
00060 #include <drizzled/temporal.h>
00061 
00062 #include <drizzled/field.h>
00063 #include <drizzled/field/str.h>
00064 #include <drizzled/field/num.h>
00065 #include <drizzled/field/blob.h>
00066 #include <drizzled/field/boolean.h>
00067 #include <drizzled/field/enum.h>
00068 #include <drizzled/field/null.h>
00069 #include <drizzled/field/date.h>
00070 #include <drizzled/field/decimal.h>
00071 #include <drizzled/field/real.h>
00072 #include <drizzled/field/double.h>
00073 #include <drizzled/field/int32.h>
00074 #include <drizzled/field/int64.h>
00075 #include <drizzled/field/size.h>
00076 #include <drizzled/field/num.h>
00077 #include <drizzled/field/time.h>
00078 #include <drizzled/field/epoch.h>
00079 #include <drizzled/field/datetime.h>
00080 #include <drizzled/field/microtime.h>
00081 #include <drizzled/field/varstring.h>
00082 #include <drizzled/field/uuid.h>
00083 #include <drizzled/field/ipv6.h>
00084 #include <drizzled/plugin/storage_engine.h>
00085 #include <drizzled/definition/cache.h>
00086 #include <drizzled/typelib.h>
00087 #include <drizzled/key.h>
00088 #include <drizzled/open_tables_state.h>
00089 
00090 using namespace std;
00091 
00092 namespace drizzled {
00093 
00094 extern size_t table_def_size;
00095 
00096 static enum_field_types proto_field_type_to_drizzle_type(const message::Table::Field &field)
00097 {
00098   switch(field.type())
00099   {
00100   case message::Table::Field::INTEGER:
00101     return DRIZZLE_TYPE_LONG;
00102 
00103   case message::Table::Field::DOUBLE:
00104     return DRIZZLE_TYPE_DOUBLE;
00105 
00106   case message::Table::Field::EPOCH:
00107     if (field.has_time_options() and field.time_options().microseconds())
00108       return DRIZZLE_TYPE_MICROTIME;
00109 
00110     return DRIZZLE_TYPE_TIMESTAMP;
00111 
00112   case message::Table::Field::BIGINT:
00113     return DRIZZLE_TYPE_LONGLONG;
00114 
00115   case message::Table::Field::DATETIME:
00116     return DRIZZLE_TYPE_DATETIME;
00117 
00118   case message::Table::Field::DATE:
00119     return DRIZZLE_TYPE_DATE;
00120 
00121   case message::Table::Field::VARCHAR:
00122     return DRIZZLE_TYPE_VARCHAR;
00123 
00124   case message::Table::Field::DECIMAL:
00125     return DRIZZLE_TYPE_DECIMAL;
00126 
00127   case message::Table::Field::ENUM:
00128     return DRIZZLE_TYPE_ENUM;
00129 
00130   case message::Table::Field::BLOB:
00131     return DRIZZLE_TYPE_BLOB;
00132 
00133   case message::Table::Field::UUID:
00134     return  DRIZZLE_TYPE_UUID;
00135 
00136   case message::Table::Field::IPV6:
00137     return  DRIZZLE_TYPE_IPV6;
00138 
00139   case message::Table::Field::BOOLEAN:
00140     return DRIZZLE_TYPE_BOOLEAN;
00141 
00142   case message::Table::Field::TIME:
00143     return DRIZZLE_TYPE_TIME;
00144   }
00145 
00146   abort();
00147 }
00148 
00149 static Item* default_value_item(enum_field_types field_type, const charset_info_st& charset, bool default_null, 
00150   const string& default_value, const string& default_bin_value)
00151 {
00152   if (default_null)
00153     return new Item_null();
00154 
00155   switch (field_type)
00156   {
00157   case DRIZZLE_TYPE_LONG:
00158   case DRIZZLE_TYPE_LONGLONG:
00159     {
00160       int error= 0;
00161       Item* default_item= new Item_int(default_value.c_str(), (int64_t) internal::my_strtoll10(default_value.c_str(), NULL, &error), default_value.length());
00162 
00163       if (error && error != -1) /* was an error and wasn't a negative number */
00164       {
00165         delete default_item;
00166         return NULL;
00167       }
00168       return default_item;
00169     }
00170   case DRIZZLE_TYPE_DOUBLE:
00171     return new Item_float(default_value.c_str(), default_value.length());
00172   case DRIZZLE_TYPE_NULL:
00173     assert(false);
00174     abort();
00175   case DRIZZLE_TYPE_TIMESTAMP:
00176   case DRIZZLE_TYPE_DATETIME:
00177   case DRIZZLE_TYPE_TIME:
00178   case DRIZZLE_TYPE_DATE:
00179   case DRIZZLE_TYPE_ENUM:
00180   case DRIZZLE_TYPE_UUID:
00181   case DRIZZLE_TYPE_IPV6:
00182   case DRIZZLE_TYPE_MICROTIME:
00183   case DRIZZLE_TYPE_BOOLEAN:
00184     // return new Item_string(*default_value, system_charset_info); // crash
00185     return new Item_string(default_value.data(), default_value.size(), system_charset_info);
00186   case DRIZZLE_TYPE_VARCHAR:
00187   case DRIZZLE_TYPE_BLOB: /* Blob is here due to TINYTEXT. Feel the hate. */
00188     return &charset== &my_charset_bin
00189       ? new Item_string(default_bin_value, &my_charset_bin)
00190       : new Item_string(default_value, system_charset_info);
00191   case DRIZZLE_TYPE_DECIMAL:
00192     return new Item_decimal(default_value.c_str(), default_value.length(), system_charset_info);
00193   }
00194   return NULL;
00195 }
00196 
00197 
00198 
00204 bool TableShare::fieldInPrimaryKey(Field *in_field) const
00205 {
00206   assert(getTableMessage());
00207 
00208   size_t num_indexes= getTableMessage()->indexes_size();
00209 
00210   for (size_t x= 0; x < num_indexes; ++x)
00211   {
00212     const message::Table::Index &index= getTableMessage()->indexes(x);
00213     if (index.is_primary())
00214     {
00215       size_t num_parts= index.index_part_size();
00216       for (size_t y= 0; y < num_parts; ++y)
00217       {
00218         if (index.index_part(y).fieldnr() == in_field->position())
00219           return true;
00220       }
00221     }
00222   }
00223   return false;
00224 }
00225 
00226 TableShare::TableShare(const identifier::Table::Type type_arg) :
00227   table_category(TABLE_UNKNOWN_CATEGORY),
00228   found_next_number_field(NULL),
00229   timestamp_field(NULL),
00230   key_info(NULL),
00231   mem_root(TABLE_ALLOC_BLOCK_SIZE),
00232   all_set(),
00233   block_size(0),
00234   version(0),
00235   timestamp_offset(0),
00236   reclength(0),
00237   stored_rec_length(0),
00238   max_rows(0),
00239   _table_message(NULL),
00240   storage_engine(NULL),
00241   tmp_table(type_arg),
00242   _ref_count(0),
00243   null_bytes(0),
00244   last_null_bit_pos(0),
00245   _field_size(0),
00246   rec_buff_length(0),
00247   keys(0),
00248   key_parts(0),
00249   max_key_length(0),
00250   max_unique_length(0),
00251   total_key_length(0),
00252   uniques(0),
00253   null_fields(0),
00254   blob_fields(0),
00255   has_variable_width(false),
00256   db_create_options(0),
00257   db_options_in_use(0),
00258   db_record_offset(0),
00259   rowid_field_offset(0),
00260   primary_key(MAX_KEY),
00261   next_number_index(0),
00262   next_number_key_offset(0),
00263   next_number_keypart(0),
00264   error(0),
00265   open_errno(0),
00266   errarg(0),
00267   blob_ptr_size(portable_sizeof_char_ptr),
00268   db_low_byte_first(false),
00269   keys_in_use(0),
00270   keys_for_keyread(0)
00271 {
00272   if (type_arg == message::Table::INTERNAL)
00273   {
00274     string s= identifier::Table::build_tmptable_filename();
00275     private_key_for_cache.vectorPtr().assign(s.c_str(), s.c_str() + s.size() + 1);
00276     init(private_key_for_cache.vector(), private_key_for_cache.vector());
00277   }
00278   else
00279   {
00280     init("", "");
00281   }
00282 }
00283 
00284 TableShare::TableShare(const identifier::Table &identifier, const identifier::Table::Key &key) :// Used by placeholder
00285   table_category(TABLE_UNKNOWN_CATEGORY),
00286   found_next_number_field(NULL),
00287   timestamp_field(NULL),
00288   key_info(NULL),
00289   mem_root(TABLE_ALLOC_BLOCK_SIZE),
00290   table_charset(0),
00291   all_set(),
00292   block_size(0),
00293   version(0),
00294   timestamp_offset(0),
00295   reclength(0),
00296   stored_rec_length(0),
00297   max_rows(0),
00298   _table_message(NULL),
00299   storage_engine(NULL),
00300   tmp_table(message::Table::INTERNAL),
00301   _ref_count(0),
00302   null_bytes(0),
00303   last_null_bit_pos(0),
00304   _field_size(0),
00305   rec_buff_length(0),
00306   keys(0),
00307   key_parts(0),
00308   max_key_length(0),
00309   max_unique_length(0),
00310   total_key_length(0),
00311   uniques(0),
00312   null_fields(0),
00313   blob_fields(0),
00314   has_variable_width(false),
00315   db_create_options(0),
00316   db_options_in_use(0),
00317   db_record_offset(0),
00318   rowid_field_offset(0),
00319   primary_key(MAX_KEY),
00320   next_number_index(0),
00321   next_number_key_offset(0),
00322   next_number_keypart(0),
00323   error(0),
00324   open_errno(0),
00325   errarg(0),
00326   blob_ptr_size(portable_sizeof_char_ptr),
00327   db_low_byte_first(false),
00328   keys_in_use(0),
00329   keys_for_keyread(0)
00330 {
00331   assert(identifier.getKey() == key);
00332 
00333   private_key_for_cache= key;
00334 
00335   table_category=         TABLE_CATEGORY_TEMPORARY;
00336   tmp_table=              message::Table::INTERNAL;
00337 
00338   db= str_ref(private_key_for_cache.vector() + strlen(private_key_for_cache.vector()) + 1);
00339 
00340   table_name= str_ref(db.data() + strlen(db.data()) + 1);
00341   path= str_ref("");
00342   normalized_path= str_ref("");
00343 
00344   std::string tb_name(identifier.getTableName());
00345   boost::to_lower(tb_name);
00346   assert(strcmp(tb_name.c_str(), table_name.data()) == 0);
00347   assert(strcmp(identifier.getSchemaName().c_str(), db.data()) == 0);
00348 }
00349 
00350 TableShare::TableShare(const identifier::Table &identifier) : // Just used during createTable()
00351   table_category(TABLE_UNKNOWN_CATEGORY),
00352   found_next_number_field(NULL),
00353   timestamp_field(NULL),
00354   key_info(NULL),
00355   mem_root(TABLE_ALLOC_BLOCK_SIZE),
00356   table_charset(0),
00357   all_set(),
00358   block_size(0),
00359   version(0),
00360   timestamp_offset(0),
00361   reclength(0),
00362   stored_rec_length(0),
00363   max_rows(0),
00364   _table_message(NULL),
00365   storage_engine(NULL),
00366   tmp_table(identifier.getType()),
00367   _ref_count(0),
00368   null_bytes(0),
00369   last_null_bit_pos(0),
00370   _field_size(0),
00371   rec_buff_length(0),
00372   keys(0),
00373   key_parts(0),
00374   max_key_length(0),
00375   max_unique_length(0),
00376   total_key_length(0),
00377   uniques(0),
00378   null_fields(0),
00379   blob_fields(0),
00380   has_variable_width(false),
00381   db_create_options(0),
00382   db_options_in_use(0),
00383   db_record_offset(0),
00384   rowid_field_offset(0),
00385   primary_key(MAX_KEY),
00386   next_number_index(0),
00387   next_number_key_offset(0),
00388   next_number_keypart(0),
00389   error(0),
00390   open_errno(0),
00391   errarg(0),
00392   blob_ptr_size(portable_sizeof_char_ptr),
00393   db_low_byte_first(false),
00394   keys_in_use(0),
00395   keys_for_keyread(0)
00396 {
00397   private_key_for_cache= identifier.getKey();
00398   assert(identifier.getPath().size()); // Since we are doing a create table, this should be a positive value
00399   private_normalized_path.resize(identifier.getPath().size() + 1);
00400   memcpy(&private_normalized_path[0], identifier.getPath().c_str(), identifier.getPath().size());
00401 
00402   {
00403     table_category= TABLE_CATEGORY_TEMPORARY;
00404     tmp_table= message::Table::INTERNAL;
00405     db= str_ref(private_key_for_cache.vector());
00406     table_name= str_ref(db.data() + 1);
00407     path= private_normalized_path;
00408     normalized_path= path;
00409   }
00410 }
00411 
00412 
00413 /*
00414   Used for shares that will go into the cache.
00415 */
00416 TableShare::TableShare(const identifier::Table::Type type_arg,
00417                        const identifier::Table &identifier,
00418                        const char *path_arg,
00419                        uint32_t path_length_arg) :
00420   table_category(TABLE_UNKNOWN_CATEGORY),
00421   found_next_number_field(NULL),
00422   timestamp_field(NULL),
00423   key_info(NULL),
00424   mem_root(TABLE_ALLOC_BLOCK_SIZE),
00425   table_charset(0),
00426   all_set(),
00427   block_size(0),
00428   version(0),
00429   timestamp_offset(0),
00430   reclength(0),
00431   stored_rec_length(0),
00432   max_rows(0),
00433   _table_message(NULL),
00434   storage_engine(NULL),
00435   tmp_table(type_arg),
00436   _ref_count(0),
00437   null_bytes(0),
00438   last_null_bit_pos(0),
00439   _field_size(0),
00440   rec_buff_length(0),
00441   keys(0),
00442   key_parts(0),
00443   max_key_length(0),
00444   max_unique_length(0),
00445   total_key_length(0),
00446   uniques(0),
00447   null_fields(0),
00448   blob_fields(0),
00449   has_variable_width(false),
00450   db_create_options(0),
00451   db_options_in_use(0),
00452   db_record_offset(0),
00453   rowid_field_offset(0),
00454   primary_key(MAX_KEY),
00455   next_number_index(0),
00456   next_number_key_offset(0),
00457   next_number_keypart(0),
00458   error(0),
00459   open_errno(0),
00460   errarg(0),
00461   blob_ptr_size(portable_sizeof_char_ptr),
00462   db_low_byte_first(false),
00463   keys_in_use(0),
00464   keys_for_keyread(0)
00465 {
00466 
00467   private_key_for_cache= identifier.getKey();
00468   /*
00469     Let us use the fact that the key is "db/0/table_name/0" + optional
00470     part for temporary tables.
00471   */
00472   db= str_ref(private_key_for_cache.vector() + strlen(private_key_for_cache.vector()) + 1);
00473   table_name= str_ref(db.data() + db.size() + 1);
00474 
00475   std::string _path;
00476   if (path_arg)
00477   {
00478     _path.assign(path_arg, path_length_arg);
00479   }
00480   else
00481   {
00482     _path= identifier::Table::build_table_filename(db.data(), table_name.data(), false);
00483   }
00484 
00485   char* path_buff= mem_root.strdup(_path);
00486   path= str_ref(path_buff, _path.length());
00487   normalized_path= str_ref(path_buff, _path.length());
00488 
00489   version= g_refresh_version;
00490 }
00491 
00492 void TableShare::init(const char *new_table_name, const char *new_path)
00493 {
00494   table_category= TABLE_CATEGORY_TEMPORARY;
00495   tmp_table= message::Table::INTERNAL;
00496   db= str_ref("");
00497   table_name= str_ref(new_table_name);
00498   path= str_ref(new_path);
00499   normalized_path= str_ref(new_path);
00500 }
00501 
00502 TableShare::~TableShare() 
00503 {
00504   storage_engine= NULL;
00505 
00506   mem_root.free_root(MYF(0));                 // Free's share
00507 }
00508 
00509 void TableShare::setIdentifier(const identifier::Table &identifier_arg)
00510 {
00511   private_key_for_cache= identifier_arg.getKey();
00512 
00513   /*
00514     Let us use the fact that the key is "db/0/table_name/0" + optional
00515     part for temporary tables.
00516   */
00517   db= str_ref(private_key_for_cache.vector() + strlen(private_key_for_cache.vector()) + 1);
00518   table_name= str_ref(db.data() + db.size() + 1);
00519 
00520   getTableMessage()->set_name(identifier_arg.getTableName());
00521   getTableMessage()->set_schema(identifier_arg.getSchemaName());
00522 }
00523 
00524 bool TableShare::parse_table_proto(Session& session, const message::Table &table)
00525 {
00526   drizzled::error_t local_error= EE_OK;
00527 
00528   if (! table.IsInitialized())
00529   {
00530     my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
00531              table.name().empty() ? " " :  table.name().c_str(),
00532              table.InitializationErrorString().c_str());
00533 
00534     return ER_CORRUPT_TABLE_DEFINITION;
00535   }
00536 
00537   setTableMessage(table);
00538 
00539   storage_engine= plugin::StorageEngine::findByName(session, table.engine().name());
00540   assert(storage_engine); // We use an assert() here because we should never get this far and still have no suitable engine.
00541 
00542   message::Table::TableOptions table_options;
00543 
00544   if (table.has_options())
00545     table_options= table.options();
00546 
00547   uint32_t local_db_create_options= 0;
00548 
00549   if (table_options.pack_record())
00550     local_db_create_options|= HA_OPTION_PACK_RECORD;
00551 
00552   /* local_db_create_options was stored as 2 bytes in FRM
00553     Any HA_OPTION_ that doesn't fit into 2 bytes was silently truncated away.
00554   */
00555   db_create_options= (local_db_create_options & 0x0000FFFF);
00556   db_options_in_use= db_create_options;
00557 
00558   block_size= table_options.has_block_size() ? table_options.block_size() : 0;
00559 
00560   table_charset= get_charset(table_options.collation_id());
00561 
00562   if (not table_charset)
00563   {
00564     my_error(ER_CORRUPT_TABLE_DEFINITION_UNKNOWN_COLLATION, MYF(0),
00565              table_options.collation().c_str(),
00566              table.name().c_str());
00567 
00568     return ER_CORRUPT_TABLE_DEFINITION; // Historical
00569   }
00570 
00571   db_record_offset= 1;
00572 
00573   keys= table.indexes_size();
00574 
00575   key_parts= 0;
00576   for (int indx= 0; indx < table.indexes_size(); indx++)
00577     key_parts+= table.indexes(indx).index_part_size();
00578 
00579   key_info= (KeyInfo*) mem().alloc(table.indexes_size() * sizeof(KeyInfo) +key_parts*sizeof(KeyPartInfo));
00580 
00581   KeyPartInfo *key_part;
00582 
00583   key_part= reinterpret_cast<KeyPartInfo*>
00584     (key_info+table.indexes_size());
00585 
00586 
00587   ulong *rec_per_key= (ulong*) mem().alloc(sizeof(ulong*)*key_parts);
00588 
00589   KeyInfo* keyinfo= key_info;
00590   for (int keynr= 0; keynr < table.indexes_size(); keynr++, keyinfo++)
00591   {
00592     message::Table::Index indx= table.indexes(keynr);
00593 
00594     keyinfo->table= 0;
00595     keyinfo->flags= 0;
00596 
00597     if (indx.is_unique())
00598       keyinfo->flags|= HA_NOSAME;
00599 
00600     if (indx.has_options())
00601     {
00602       message::Table::Index::Options indx_options= indx.options();
00603       if (indx_options.pack_key())
00604         keyinfo->flags|= HA_PACK_KEY;
00605 
00606       if (indx_options.var_length_key())
00607         keyinfo->flags|= HA_VAR_LENGTH_PART;
00608 
00609       if (indx_options.null_part_key())
00610         keyinfo->flags|= HA_NULL_PART_KEY;
00611 
00612       if (indx_options.binary_pack_key())
00613         keyinfo->flags|= HA_BINARY_PACK_KEY;
00614 
00615       if (indx_options.has_partial_segments())
00616         keyinfo->flags|= HA_KEY_HAS_PART_KEY_SEG;
00617 
00618       if (indx_options.auto_generated_key())
00619         keyinfo->flags|= HA_GENERATED_KEY;
00620 
00621       if (indx_options.has_key_block_size())
00622       {
00623         keyinfo->flags|= HA_USES_BLOCK_SIZE;
00624         keyinfo->block_size= indx_options.key_block_size();
00625       }
00626       else
00627       {
00628         keyinfo->block_size= 0;
00629       }
00630     }
00631 
00632     switch (indx.type())
00633     {
00634     case message::Table::Index::UNKNOWN_INDEX:
00635       keyinfo->algorithm= HA_KEY_ALG_UNDEF;
00636       break;
00637     case message::Table::Index::BTREE:
00638       keyinfo->algorithm= HA_KEY_ALG_BTREE;
00639       break;
00640     case message::Table::Index::HASH:
00641       keyinfo->algorithm= HA_KEY_ALG_HASH;
00642       break;
00643 
00644     default:
00645       /* TODO: suitable warning ? */
00646       keyinfo->algorithm= HA_KEY_ALG_UNDEF;
00647       break;
00648     }
00649 
00650     keyinfo->key_length= indx.key_length();
00651 
00652     keyinfo->key_parts= indx.index_part_size();
00653 
00654     keyinfo->key_part= key_part;
00655     keyinfo->rec_per_key= rec_per_key;
00656 
00657     for (unsigned int partnr= 0;
00658          partnr < keyinfo->key_parts;
00659          partnr++, key_part++)
00660     {
00661       message::Table::Index::IndexPart part;
00662       part= indx.index_part(partnr);
00663 
00664       *rec_per_key++= 0;
00665 
00666       key_part->field= NULL;
00667       key_part->fieldnr= part.fieldnr() + 1; // start from 1.
00668       key_part->null_bit= 0;
00669       /* key_part->null_offset is only set if null_bit (see later) */
00670       /* key_part->key_type= */ /* I *THINK* this may be okay.... */
00671       /* key_part->type ???? */
00672       key_part->key_part_flag= 0;
00673       if (part.has_in_reverse_order())
00674         key_part->key_part_flag= part.in_reverse_order()? HA_REVERSE_SORT : 0;
00675 
00676       key_part->length= part.compare_length();
00677 
00678       int mbmaxlen= 1;
00679 
00680       if (table.field(part.fieldnr()).type() == message::Table::Field::VARCHAR
00681           || table.field(part.fieldnr()).type() == message::Table::Field::BLOB)
00682       {
00683         uint32_t collation_id;
00684 
00685         if (table.field(part.fieldnr()).string_options().has_collation_id())
00686           collation_id= table.field(part.fieldnr()).string_options().collation_id();
00687         else
00688           collation_id= table.options().collation_id();
00689 
00690         const charset_info_st *cs= get_charset(collation_id);
00691 
00692         mbmaxlen= cs->mbmaxlen;
00693       }
00694       key_part->length*= mbmaxlen;
00695 
00696       key_part->store_length= key_part->length;
00697 
00698       /* key_part->offset is set later */
00699       key_part->key_type= 0;
00700     }
00701 
00702     if (not indx.has_comment())
00703     {
00704       keyinfo->comment.clear();
00705     }
00706     else
00707     {
00708       keyinfo->flags|= HA_USES_COMMENT;
00709       keyinfo->comment.assign(mem().strdup(indx.comment()), indx.comment().length());
00710     }
00711 
00712     keyinfo->name= mem().strdup(indx.name());
00713 
00714     addKeyName(string(keyinfo->name, indx.name().length()));
00715   }
00716 
00717   keys_for_keyread.reset();
00718   set_prefix(keys_in_use, keys);
00719 
00720   _field_size= table.field_size();
00721 
00722   setFields(_field_size + 1);
00723   _fields[_field_size]= NULL;
00724 
00725   uint32_t local_null_fields= 0;
00726   reclength= 0;
00727 
00728   std::vector<uint32_t> field_offsets;
00729   std::vector<uint32_t> field_pack_length;
00730 
00731   field_offsets.resize(_field_size);
00732   field_pack_length.resize(_field_size);
00733 
00734   uint32_t interval_count= 0;
00735   uint32_t interval_parts= 0;
00736 
00737   uint32_t stored_columns_reclength= 0;
00738 
00739   for (unsigned int fieldnr= 0; fieldnr < _field_size; fieldnr++)
00740   {
00741     message::Table::Field pfield= table.field(fieldnr);
00742     if (pfield.constraints().is_nullable()) // Historical reference
00743     {
00744       local_null_fields++;
00745     }
00746     else if (not pfield.constraints().is_notnull())
00747     {
00748       local_null_fields++;
00749     }
00750 
00751     enum_field_types drizzle_field_type= proto_field_type_to_drizzle_type(pfield);
00752 
00753     field_offsets[fieldnr]= stored_columns_reclength;
00754 
00755     /* the below switch is very similar to
00756       CreateField::create_length_to_internal_length in field.cc
00757       (which should one day be replace by just this code)
00758     */
00759     switch(drizzle_field_type)
00760     {
00761     case DRIZZLE_TYPE_BLOB:
00762     case DRIZZLE_TYPE_VARCHAR:
00763       {
00764         message::Table::Field::StringFieldOptions field_options= pfield.string_options();
00765 
00766         const charset_info_st *cs= get_charset(field_options.has_collation_id() ?
00767                                             field_options.collation_id() : 0);
00768 
00769         if (! cs)
00770           cs= default_charset_info;
00771 
00772         field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type,
00773                                                      field_options.length() * cs->mbmaxlen);
00774       }
00775       break;
00776     case DRIZZLE_TYPE_ENUM:
00777       {
00778         message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
00779 
00780         field_pack_length[fieldnr]= 4;
00781 
00782         interval_count++;
00783         interval_parts+= field_options.field_value_size();
00784       }
00785       break;
00786     case DRIZZLE_TYPE_DECIMAL:
00787       {
00788         message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
00789 
00790         field_pack_length[fieldnr]= class_decimal_get_binary_size(fo.precision(), fo.scale());
00791       }
00792       break;
00793     default:
00794       /* Zero is okay here as length is fixed for other types. */
00795       field_pack_length[fieldnr]= calc_pack_length(drizzle_field_type, 0);
00796     }
00797 
00798     reclength+= field_pack_length[fieldnr];
00799     stored_columns_reclength+= field_pack_length[fieldnr];
00800   }
00801 
00802   /* data_offset added to stored_rec_length later */
00803   stored_rec_length= stored_columns_reclength;
00804 
00805   null_fields= local_null_fields;
00806 
00807   ulong null_bits= local_null_fields;
00808   if (! table_options.pack_record())
00809     null_bits++;
00810   ulong data_offset= (null_bits + 7)/8;
00811 
00812 
00813   reclength+= data_offset;
00814   stored_rec_length+= data_offset;
00815 
00816   ulong local_rec_buff_length;
00817 
00818   local_rec_buff_length= ALIGN_SIZE(reclength + 1);
00819   rec_buff_length= local_rec_buff_length;
00820 
00821   resizeDefaultValues(local_rec_buff_length);
00822   unsigned char* record= getDefaultValues();
00823   int null_count= 0;
00824 
00825   if (! table_options.pack_record())
00826   {
00827     null_count++; // one bit for delete mark.
00828     *record|= 1;
00829   }
00830 
00831 
00832   intervals.resize(interval_count);
00833 
00834   /* Now fix the TYPELIBs for the intervals (enum values)
00835     and field names.
00836   */
00837 
00838   uint32_t interval_nr= 0;
00839 
00840   for (unsigned int fieldnr= 0; fieldnr < _field_size; fieldnr++)
00841   {
00842     message::Table::Field pfield= table.field(fieldnr);
00843 
00844     /* enum typelibs */
00845     if (pfield.type() != message::Table::Field::ENUM)
00846       continue;
00847 
00848     message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
00849 
00850     if (field_options.field_value_size() > Field_enum::max_supported_elements)
00851     {
00852       my_error(ER_CORRUPT_TABLE_DEFINITION_ENUM, MYF(0), table.name().c_str());
00853 
00854       return ER_CORRUPT_TABLE_DEFINITION_ENUM; // Historical
00855     }
00856 
00857 
00858     const charset_info_st *charset= get_charset(field_options.has_collation_id() ?
00859                                              field_options.collation_id() : 0);
00860 
00861     if (! charset)
00862       charset= default_charset_info;
00863 
00864     TYPELIB *t= (&intervals[interval_nr]);
00865 
00866     t->type_names= (const char**)mem().alloc((field_options.field_value_size() + 1) * sizeof(char*));
00867     t->type_lengths= (unsigned int*)mem().alloc((field_options.field_value_size() + 1) * sizeof(unsigned int));
00868 
00869     t->type_names[field_options.field_value_size()]= NULL;
00870     t->type_lengths[field_options.field_value_size()]= 0;
00871 
00872     t->count= field_options.field_value_size();
00873     t->name= NULL;
00874 
00875     for (int n= 0; n < field_options.field_value_size(); n++)
00876     {
00877       t->type_names[n]= mem().strdup(field_options.field_value(n));
00878 
00879       /* 
00880        * Go ask the charset what the length is as for "" length=1
00881        * and there's stripping spaces or some other crack going on.
00882      */
00883       t->type_lengths[n]= charset->cset->lengthsp(charset, t->type_names[n], field_options.field_value(n).length());
00884     }
00885     interval_nr++;
00886   }
00887 
00888 
00889   /* and read the fields */
00890   interval_nr= 0;
00891 
00892   bool use_hash= _field_size >= MAX_FIELDS_BEFORE_HASH;
00893 
00894   unsigned char* null_pos= getDefaultValues();
00895   int null_bit_pos= (table_options.pack_record()) ? 0 : 1;
00896 
00897   for (unsigned int fieldnr= 0; fieldnr < _field_size; fieldnr++)
00898   {
00899     message::Table::Field pfield= table.field(fieldnr);
00900 
00901     Field::utype unireg_type= Field::NONE;
00902 
00903     if (pfield.has_numeric_options() &&
00904         pfield.numeric_options().is_autoincrement())
00905     {
00906       unireg_type= Field::NEXT_NUMBER;
00907     }
00908 
00909     if (pfield.has_options() &&
00910         pfield.options().has_default_expression() &&
00911         pfield.options().default_expression().compare("CURRENT_TIMESTAMP") == 0)
00912     {
00913       if (pfield.options().has_update_expression() &&
00914           pfield.options().update_expression().compare("CURRENT_TIMESTAMP") == 0)
00915       {
00916         unireg_type= Field::TIMESTAMP_DNUN_FIELD;
00917       }
00918       else if (! pfield.options().has_update_expression())
00919       {
00920         unireg_type= Field::TIMESTAMP_DN_FIELD;
00921       }
00922       else
00923       {
00924         assert(0); // Invalid update value.
00925         abort();
00926       }
00927     }
00928     else if (pfield.has_options() &&
00929              pfield.options().has_update_expression() &&
00930              pfield.options().update_expression().compare("CURRENT_TIMESTAMP") == 0)
00931     {
00932       unireg_type= Field::TIMESTAMP_UN_FIELD;
00933     }
00934 
00935     str_ref comment;
00936     if (pfield.has_comment())
00937     {
00938       comment.assign(mem().strdup(pfield.comment()), pfield.comment().size());
00939     }
00940 
00941     enum_field_types field_type;
00942 
00943     field_type= proto_field_type_to_drizzle_type(pfield);
00944 
00945     const charset_info_st *charset= &my_charset_bin;
00946 
00947     if (field_type == DRIZZLE_TYPE_BLOB || field_type == DRIZZLE_TYPE_VARCHAR)
00948     {
00949       message::Table::Field::StringFieldOptions field_options= pfield.string_options();
00950 
00951       charset= get_charset(field_options.has_collation_id() ? field_options.collation_id() : 0);
00952 
00953       if (not charset)
00954         charset= default_charset_info;
00955     }
00956 
00957     if (field_type == DRIZZLE_TYPE_ENUM)
00958     {
00959       message::Table::Field::EnumerationValues field_options= pfield.enumeration_values();
00960 
00961       charset= get_charset(field_options.has_collation_id() ? field_options.collation_id() : 0);
00962 
00963       if (not charset)
00964         charset= default_charset_info;
00965     }
00966 
00967     uint8_t decimals= 0;
00968     if (field_type == DRIZZLE_TYPE_DECIMAL || field_type == DRIZZLE_TYPE_DOUBLE)
00969     {
00970       message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
00971 
00972       if (not pfield.has_numeric_options() || ! fo.has_scale())
00973       {
00974         /*
00975           We don't write the default to table proto so
00976           if no decimals specified for DOUBLE, we use the default.
00977         */
00978         decimals= NOT_FIXED_DEC;
00979       }
00980       else
00981       {
00982         if (fo.scale() > DECIMAL_MAX_SCALE)
00983         {
00984           local_error= ER_NOT_FORM_FILE;
00985 
00986           return true;
00987         }
00988         decimals= static_cast<uint8_t>(fo.scale());
00989       }
00990     }
00991 
00992     Item *default_value= NULL;
00993 
00994     if (pfield.options().has_default_value() ||
00995         pfield.options().default_null()  ||
00996         pfield.options().has_default_bin_value())
00997     {
00998       default_value= default_value_item(field_type, *charset, pfield.options().default_null(), pfield.options().default_value(), pfield.options().default_bin_value());
00999       if (default_value == NULL)
01000       {
01001         my_error(ER_INVALID_DEFAULT, MYF(0), pfield.name().c_str());
01002         return true;
01003       }
01004     }
01005 
01006 
01007     uint32_t field_length= 0; //Assignment is for compiler complaint.
01008 
01009     // We set field_length in this loop.
01010     switch (field_type)
01011     {
01012     case DRIZZLE_TYPE_BLOB:
01013     case DRIZZLE_TYPE_VARCHAR:
01014       {
01015         message::Table::Field::StringFieldOptions field_options= pfield.string_options();
01016 
01017         charset= get_charset(field_options.has_collation_id() ?
01018                              field_options.collation_id() : 0);
01019 
01020         if (! charset)
01021           charset= default_charset_info;
01022 
01023         field_length= field_options.length() * charset->mbmaxlen;
01024       }
01025       break;
01026     case DRIZZLE_TYPE_DOUBLE:
01027       {
01028         message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
01029         if (!fo.has_precision() && !fo.has_scale())
01030         {
01031           field_length= DBL_DIG+7;
01032         }
01033         else
01034         {
01035           field_length= fo.precision();
01036         }
01037         if (field_length < decimals &&
01038             decimals != NOT_FIXED_DEC)
01039         {
01040           my_error(ER_M_BIGGER_THAN_D, MYF(0), pfield.name().c_str());
01041           local_error= ER_M_BIGGER_THAN_D;
01042           return true;
01043         }
01044         break;
01045       }
01046     case DRIZZLE_TYPE_DECIMAL:
01047       {
01048         message::Table::Field::NumericFieldOptions fo= pfield.numeric_options();
01049 
01050         field_length= class_decimal_precision_to_length(fo.precision(), fo.scale(),
01051                                                      false);
01052         break;
01053       }
01054     case DRIZZLE_TYPE_DATETIME:
01055       field_length= DateTime::MAX_STRING_LENGTH;
01056       break;
01057     case DRIZZLE_TYPE_DATE:
01058       field_length= Date::MAX_STRING_LENGTH;
01059       break;
01060     case DRIZZLE_TYPE_ENUM:
01061       {
01062         field_length= 0;
01063 
01064         message::Table::Field::EnumerationValues fo= pfield.enumeration_values();
01065 
01066         for (int valnr= 0; valnr < fo.field_value_size(); valnr++)
01067         {
01068           if (fo.field_value(valnr).length() > field_length)
01069           {
01070             field_length= charset->cset->numchars(charset,
01071                                                   fo.field_value(valnr).c_str(),
01072                                                   fo.field_value(valnr).c_str()
01073                                                   + fo.field_value(valnr).length())
01074               * charset->mbmaxlen;
01075           }
01076         }
01077       }
01078       break;
01079     case DRIZZLE_TYPE_LONG:
01080       {
01081         uint32_t sign_len= pfield.constraints().is_unsigned() ? 0 : 1;
01082         field_length= MAX_INT_WIDTH+sign_len;
01083       }
01084       break;
01085     case DRIZZLE_TYPE_LONGLONG:
01086       {
01087         uint32_t sign_len= pfield.constraints().is_unsigned() ? 0 : 1;
01088         field_length= MAX_BIGINT_WIDTH+sign_len;
01089       }
01090       break;
01091     case DRIZZLE_TYPE_UUID:
01092       field_length= field::Uuid::max_string_length();
01093       break;
01094     case DRIZZLE_TYPE_IPV6:
01095       field_length= field::IPv6::max_string_length();
01096       break;
01097     case DRIZZLE_TYPE_BOOLEAN:
01098       field_length= field::Boolean::max_string_length();
01099       break;
01100     case DRIZZLE_TYPE_MICROTIME:
01101       field_length= field::Microtime::max_string_length();
01102       break;
01103     case DRIZZLE_TYPE_TIMESTAMP:
01104       field_length= field::Epoch::max_string_length();
01105       break;
01106     case DRIZZLE_TYPE_TIME:
01107       field_length= field::Time::max_string_length();
01108       break;
01109     case DRIZZLE_TYPE_NULL:
01110       abort(); // Programming error
01111     }
01112 
01113     bool is_not_null= false;
01114 
01115     if (not pfield.constraints().is_nullable())
01116     {
01117       is_not_null= true;
01118     }
01119     else if (pfield.constraints().is_notnull())
01120     {
01121       is_not_null= true;
01122     }
01123 
01124     Field* f= make_field(pfield,
01125                          record + field_offsets[fieldnr] + data_offset,
01126                          field_length,
01127                          not is_not_null,
01128                          null_pos,
01129                          null_bit_pos,
01130                          decimals,
01131                          field_type,
01132                          charset,
01133                          MTYP_TYPENR(unireg_type),
01134                          ((field_type == DRIZZLE_TYPE_ENUM) ?  &intervals[interval_nr++] : (TYPELIB*) 0),
01135                          getTableMessage()->field(fieldnr).name().c_str());
01136 
01137     _fields[fieldnr]= f;
01138 
01139     // Insert post make_field code here.
01140     switch (field_type)
01141     {
01142     case DRIZZLE_TYPE_BLOB:
01143     case DRIZZLE_TYPE_VARCHAR:
01144     case DRIZZLE_TYPE_DOUBLE:
01145     case DRIZZLE_TYPE_DECIMAL:
01146     case DRIZZLE_TYPE_TIMESTAMP:
01147     case DRIZZLE_TYPE_TIME:
01148     case DRIZZLE_TYPE_DATETIME:
01149     case DRIZZLE_TYPE_MICROTIME:
01150     case DRIZZLE_TYPE_DATE:
01151     case DRIZZLE_TYPE_ENUM:
01152     case DRIZZLE_TYPE_LONG:
01153     case DRIZZLE_TYPE_LONGLONG:
01154     case DRIZZLE_TYPE_NULL:
01155     case DRIZZLE_TYPE_UUID:
01156     case DRIZZLE_TYPE_IPV6:
01157     case DRIZZLE_TYPE_BOOLEAN:
01158       break;
01159     }
01160 
01161     // This needs to go, we should be setting the "use" on the field so that
01162     // it does not reference the share/table.
01163     table::Shell temp_table(*this); /* Use this so that BLOB DEFAULT '' works */
01164     temp_table.in_use= &session;
01165 
01166     f->init(&temp_table); /* blob default values need table obj */
01167 
01168     if (! (f->flags & NOT_NULL_FLAG))
01169     {
01170       *f->null_ptr|= f->null_bit;
01171       if (! (null_bit_pos= (null_bit_pos + 1) & 7)) /* @TODO Ugh. */
01172         null_pos++;
01173       null_count++;
01174     }
01175 
01176     if (default_value)
01177     {
01178       enum_check_fields old_count_cuted_fields= session.count_cuted_fields;
01179       session.count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
01180       int res= default_value->save_in_field(f, 1);
01181       session.count_cuted_fields= old_count_cuted_fields;
01182       if (res != 0 && res != 3) /* @TODO Huh? */
01183       {
01184         my_error(ER_INVALID_DEFAULT, MYF(0), f->field_name);
01185         local_error= ER_INVALID_DEFAULT;
01186 
01187         return true;
01188       }
01189     }
01190     else if (f->real_type() == DRIZZLE_TYPE_ENUM && (f->flags & NOT_NULL_FLAG))
01191     {
01192       f->set_notnull();
01193       f->store((int64_t) 1, true);
01194     }
01195     else
01196     {
01197       f->reset();
01198     }
01199 
01200     /* hack to undo f->init() */
01201     f->setTable(NULL);
01202     f->orig_table= NULL;
01203 
01204     f->setPosition(fieldnr);
01205     f->comment= comment;
01206     if (not default_value &&
01207         not (f->unireg_check==Field::NEXT_NUMBER) &&
01208         (f->flags & NOT_NULL_FLAG) &&
01209         (not f->is_timestamp()))
01210     {
01211       f->flags|= NO_DEFAULT_VALUE_FLAG;
01212     }
01213 
01214     if (f->unireg_check == Field::NEXT_NUMBER)
01215       found_next_number_field= &(_fields[fieldnr]);
01216 
01217     if (use_hash) /* supposedly this never fails... but comments lie */
01218     {
01219       const char *local_field_name= _fields[fieldnr]->field_name;
01220       name_hash.insert(make_pair(local_field_name, &(_fields[fieldnr])));
01221     }
01222   }
01223 
01224   keyinfo= key_info;
01225   for (unsigned int keynr= 0; keynr < keys; keynr++, keyinfo++)
01226   {
01227     key_part= keyinfo->key_part;
01228 
01229     for (unsigned int partnr= 0;
01230          partnr < keyinfo->key_parts;
01231          partnr++, key_part++)
01232     {
01233       /* 
01234        * Fix up key_part->offset by adding data_offset.
01235        * We really should compute offset as well.
01236        * But at least this way we are a little better.
01237      */
01238       key_part->offset= field_offsets[key_part->fieldnr-1] + data_offset;
01239     }
01240   }
01241 
01242   /*
01243     We need to set the unused bits to 1. If the number of bits is a multiple
01244     of 8 there are no unused bits.
01245   */
01246   if (null_count & 7)
01247     *(record + null_count / 8)|= ~(((unsigned char) 1 << (null_count & 7)) - 1);
01248 
01249   null_bytes= (null_pos - (unsigned char*) record + (null_bit_pos + 7) / 8);
01250 
01251   last_null_bit_pos= null_bit_pos;
01252 
01253   /* Fix key stuff */
01254   if (key_parts)
01255   {
01256     uint32_t local_primary_key= doesKeyNameExist("PRIMARY");
01257     keyinfo= key_info;
01258     key_part= keyinfo->key_part;
01259 
01260     for (uint32_t key= 0; key < keys; key++,keyinfo++)
01261     {
01262       uint32_t usable_parts= 0;
01263 
01264       if (local_primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME))
01265       {
01266         /*
01267           If the UNIQUE key doesn't have NULL columns and is not a part key
01268           declare this as a primary key.
01269         */
01270         local_primary_key=key;
01271         for (uint32_t i= 0; i < keyinfo->key_parts; i++)
01272         {
01273           uint32_t fieldnr= key_part[i].fieldnr;
01274           if (not fieldnr ||
01275               _fields[fieldnr-1]->null_ptr ||
01276               _fields[fieldnr-1]->key_length() != key_part[i].length)
01277           {
01278             local_primary_key= MAX_KEY; // Can't be used
01279             break;
01280           }
01281         }
01282       }
01283 
01284       for (uint32_t i= 0 ; i < keyinfo->key_parts ; key_part++,i++)
01285       {
01286         Field *local_field;
01287         if (! key_part->fieldnr)
01288         {
01289           return ENOMEM;
01290         }
01291         local_field= key_part->field= _fields[key_part->fieldnr-1];
01292         key_part->type= local_field->key_type();
01293         if (local_field->null_ptr)
01294         {
01295           key_part->null_offset=(uint32_t) ((unsigned char*) local_field->null_ptr - getDefaultValues());
01296           key_part->null_bit= local_field->null_bit;
01297           key_part->store_length+=HA_KEY_NULL_LENGTH;
01298           keyinfo->flags|=HA_NULL_PART_KEY;
01299           keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
01300           keyinfo->key_length+= HA_KEY_NULL_LENGTH;
01301         }
01302         if (local_field->type() == DRIZZLE_TYPE_BLOB ||
01303             local_field->real_type() == DRIZZLE_TYPE_VARCHAR)
01304         {
01305           if (local_field->type() == DRIZZLE_TYPE_BLOB)
01306             key_part->key_part_flag|= HA_BLOB_PART;
01307           else
01308             key_part->key_part_flag|= HA_VAR_LENGTH_PART;
01309           keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
01310           key_part->store_length+=HA_KEY_BLOB_LENGTH;
01311           keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
01312         }
01313         if (i == 0 && key != local_primary_key)
01314           local_field->flags |= (((keyinfo->flags & HA_NOSAME) &&
01315                                   (keyinfo->key_parts == 1)) ?
01316                                  UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
01317         if (i == 0)
01318           local_field->key_start.set(key);
01319         if (local_field->key_length() == key_part->length &&
01320             !(local_field->flags & BLOB_FLAG))
01321         {
01322           enum ha_key_alg algo= key_info[key].algorithm;
01323           if (db_type()->index_flags(algo) & HA_KEYREAD_ONLY)
01324           {
01325             keys_for_keyread.set(key);
01326             local_field->part_of_key.set(key);
01327             local_field->part_of_key_not_clustered.set(key);
01328           }
01329           if (db_type()->index_flags(algo) & HA_READ_ORDER)
01330             local_field->part_of_sortkey.set(key);
01331         }
01332         if (!(key_part->key_part_flag & HA_REVERSE_SORT) &&
01333             usable_parts == i)
01334           usable_parts++;     // For FILESORT
01335         local_field->flags|= PART_KEY_FLAG;
01336         if (key == local_primary_key)
01337         {
01338           local_field->flags|= PRI_KEY_FLAG;
01339           /*
01340             If this field is part of the primary key and all keys contains
01341             the primary key, then we can use any key to find this column
01342           */
01343           if (storage_engine->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX))
01344           {
01345             local_field->part_of_key= keys_in_use;
01346             if (local_field->part_of_sortkey.test(key))
01347               local_field->part_of_sortkey= keys_in_use;
01348           }
01349         }
01350         if (local_field->key_length() != key_part->length)
01351         {
01352           key_part->key_part_flag|= HA_PART_KEY_SEG;
01353         }
01354       }
01355       keyinfo->usable_key_parts= usable_parts; // Filesort
01356 
01357       set_if_bigger(max_key_length,keyinfo->key_length+
01358                     keyinfo->key_parts);
01359       total_key_length+= keyinfo->key_length;
01360 
01361       if (keyinfo->flags & HA_NOSAME)
01362       {
01363         set_if_bigger(max_unique_length,keyinfo->key_length);
01364       }
01365     }
01366     if (local_primary_key < MAX_KEY &&
01367         (keys_in_use.test(local_primary_key)))
01368     {
01369       primary_key= local_primary_key;
01370       /*
01371         If we are using an integer as the primary key then allow the user to
01372         refer to it as '_rowid'
01373       */
01374       if (key_info[local_primary_key].key_parts == 1)
01375       {
01376         Field *local_field= key_info[local_primary_key].key_part[0].field;
01377         if (local_field && local_field->result_type() == INT_RESULT)
01378         {
01379           /* note that fieldnr here (and rowid_field_offset) starts from 1 */
01380           rowid_field_offset= (key_info[local_primary_key].key_part[0].
01381                                       fieldnr);
01382         }
01383       }
01384     }
01385   }
01386 
01387   if (found_next_number_field)
01388   {
01389     Field *reg_field= *found_next_number_field;
01390     if ((int) (next_number_index= (uint32_t)
01391                find_ref_key(key_info, keys,
01392                             getDefaultValues(), reg_field,
01393                             &next_number_key_offset,
01394                             &next_number_keypart)) < 0)
01395     {
01396       /* Wrong field definition */
01397       local_error= ER_NOT_FORM_FILE;
01398 
01399       return true;
01400     }
01401     else
01402     {
01403       reg_field->flags |= AUTO_INCREMENT_FLAG;
01404     }
01405   }
01406 
01407   if (blob_fields)
01408   {
01409     /* Store offsets to blob fields to find them fast */
01410     blob_field.resize(blob_fields);
01411     uint32_t *save= &blob_field[0];
01412     uint32_t k= 0;
01413     for (Fields::iterator iter= _fields.begin(); iter != _fields.end()-1; iter++, k++)
01414     {
01415       if ((*iter)->flags & BLOB_FLAG)
01416         (*save++)= k;
01417     }
01418   }
01419 
01420   all_set.clear();
01421   all_set.resize(_field_size);
01422   all_set.set();
01423 
01424   return local_error != EE_OK;
01425 }
01426 
01427 /*
01428   Read table definition from a binary / text based .frm cursor
01429 
01430   SYNOPSIS
01431   open_table_def()
01432   session   Thread Cursor
01433   share   Fill this with table definition
01434 
01435   NOTES
01436   This function is called when the table definition is not cached in
01437   definition::Cache::getCache()
01438   The data is returned in 'share', which is alloced by
01439   alloc_table_share().. The code assumes that share is initialized.
01440 
01441   RETURN VALUES
01442   0 ok
01443   1 Error (see open_table_error)
01444   2    Error (see open_table_error)
01445   3    Wrong data in .frm cursor
01446   4    Error (see open_table_error)
01447   5    Error (see open_table_error: charset unavailable)
01448   6    Unknown .frm version
01449 */
01450 
01451 int TableShare::open_table_def(Session& session, const identifier::Table &identifier)
01452 {
01453   drizzled::error_t local_error= EE_OK;
01454 
01455   message::table::shared_ptr table= plugin::StorageEngine::getTableMessage(session, identifier, local_error);
01456 
01457   if (table and table->IsInitialized())
01458   {
01459     if (parse_table_proto(session, *table))
01460     {
01461       local_error= ER_CORRUPT_TABLE_DEFINITION_UNKNOWN;
01462       my_error(ER_CORRUPT_TABLE_DEFINITION_UNKNOWN, identifier);
01463     }
01464     else
01465     {
01466       setTableCategory(TABLE_CATEGORY_USER);
01467       local_error= EE_OK;
01468     }
01469   }
01470   else if (table and not table->IsInitialized())
01471   {
01472     local_error= ER_CORRUPT_TABLE_DEFINITION_UNKNOWN;
01473     my_error(ER_CORRUPT_TABLE_DEFINITION_UNKNOWN, identifier);
01474   }
01475   else
01476   {
01477     local_error= ER_TABLE_UNKNOWN;
01478     my_error(ER_TABLE_UNKNOWN, identifier);
01479   }
01480 
01481   return static_cast<int>(local_error);
01482 }
01483 
01484 
01485 /*
01486   Open a table based on a TableShare
01487 
01488   SYNOPSIS
01489   open_table_from_share()
01490   session     Thread Cursor
01491   share   Table definition
01492   alias         Alias for table
01493   db_stat   open flags (for example HA_OPEN_KEYFILE|
01494   HA_OPEN_RNDFILE..) can be 0 (example in
01495   ha_example_table)
01496   ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
01497   outparam        result table
01498 
01499   RETURN VALUES
01500   0 ok
01501   1 Error (see open_table_error)
01502   2    Error (see open_table_error)
01503   3    Wrong data in .frm cursor
01504   4    Error (see open_table_error)
01505   5    Error (see open_table_error: charset unavailable)
01506   7    Table definition has changed in engine
01507 */
01508 int TableShare::open_table_from_share(Session *session,
01509                                       const identifier::Table &identifier,
01510                                       const char *alias,
01511                                       uint32_t db_stat, uint32_t ha_open_flags,
01512                                       Table &outparam)
01513 {
01514   bool error_reported= false;
01515   int ret= open_table_from_share_inner(session, alias, db_stat, outparam);
01516 
01517   if (not ret)
01518     ret= open_table_cursor_inner(identifier, db_stat, ha_open_flags, outparam, error_reported);
01519 
01520   if (not ret)
01521     return ret;
01522 
01523   if (not error_reported)
01524     open_table_error(ret, errno, 0);
01525 
01526   boost::checked_delete(outparam.cursor);
01527   outparam.cursor= 0;       // For easier error checking
01528   outparam.db_stat= 0;
01529   outparam.mem().free_root(MYF(0));       // Safe to call on zeroed root
01530   outparam.clearAlias();
01531 
01532   return ret;
01533 }
01534 
01535 int TableShare::open_table_from_share_inner(Session *session, const char *alias, uint32_t db_stat, Table &outparam)
01536 {
01537   int local_error= 1;
01538   outparam.resetTable(session, this, db_stat);
01539 
01540   outparam.setAlias(alias);
01541 
01542   /* Allocate Cursor */
01543   if (not (outparam.cursor= db_type()->getCursor(outparam)))
01544     return local_error;
01545 
01546   local_error= 4;
01547   uint32_t records= 0;
01548   if (db_stat & HA_OPEN_KEYFILE)
01549     records=1;
01550 
01551   records++;
01552 
01553   unsigned char* record= outparam.alloc(rec_buff_length * records);
01554 
01555   if (records == 0)
01556   {
01557     /* We are probably in hard repair, and the buffers should not be used */
01558     outparam.record[0]= outparam.record[1]= getDefaultValues();
01559   }
01560   else
01561   {
01562     outparam.record[0]= record;
01563     if (records > 1)
01564       outparam.record[1]= record+ rec_buff_length;
01565     else
01566       outparam.record[1]= outparam.getInsertRecord();   // Safety
01567   }
01568 
01569 #ifdef HAVE_VALGRIND
01570   /*
01571     We need this because when we read var-length rows, we are not updating
01572     bytes after end of varchar
01573   */
01574   if (records > 1)
01575   {
01576     memcpy(outparam.getInsertRecord(), getDefaultValues(), rec_buff_length);
01577     memcpy(outparam.getUpdateRecord(), getDefaultValues(), null_bytes);
01578     if (records > 2)
01579       memcpy(outparam.getUpdateRecord(), getDefaultValues(), rec_buff_length);
01580   }
01581 #endif
01582   if (records > 1)
01583   {
01584     memcpy(outparam.getUpdateRecord(), getDefaultValues(), null_bytes);
01585   }
01586 
01587   Field** field_ptr = new (outparam.mem()) Field*[_field_size + 1];
01588 
01589   outparam.setFields(field_ptr);
01590 
01591   record= outparam.getInsertRecord()-1; /* Fieldstart = 1 */
01592 
01593   outparam.null_flags= (unsigned char*) record+1;
01594 
01595   /* Setup copy of fields from share, but use the right alias and record */
01596   for (uint32_t i= 0 ; i < _field_size; i++, field_ptr++)
01597   {
01598     if (!((*field_ptr)= _fields[i]->clone(&outparam.mem(), &outparam)))
01599       return local_error;
01600   }
01601   *field_ptr= 0;                              // End marker
01602 
01603   if (found_next_number_field)
01604     outparam.found_next_number_field=
01605       outparam.getField(positionFields(found_next_number_field));
01606   if (timestamp_field)
01607     outparam.timestamp_field= (field::Epoch*) outparam.getField(timestamp_field->position());
01608 
01609   /* Fix key->name and key_part->field */
01610   if (key_parts)
01611   {
01612     uint32_t n_length= keys * sizeof(KeyInfo) + key_parts * sizeof(KeyPartInfo);
01613     KeyInfo* local_key_info= (KeyInfo*) outparam.alloc(n_length);
01614     outparam.key_info= local_key_info;
01615     KeyPartInfo* key_part= reinterpret_cast<KeyPartInfo*>(local_key_info+keys);
01616 
01617     memcpy(local_key_info, key_info, sizeof(*local_key_info)*keys);
01618     memcpy(key_part, key_info[0].key_part, sizeof(*key_part) * key_parts);
01619 
01620     for (KeyInfo* key_info_end= local_key_info + keys; local_key_info < key_info_end; local_key_info++)
01621     {
01622       local_key_info->table= &outparam;
01623       local_key_info->key_part= key_part;
01624 
01625       for (KeyPartInfo* key_part_end= key_part+ local_key_info->key_parts; key_part < key_part_end; key_part++)
01626       {
01627         Field *local_field= key_part->field= outparam.getField(key_part->fieldnr-1);
01628 
01629         if (local_field->key_length() != key_part->length && not (local_field->flags & BLOB_FLAG))
01630         {
01631           /*
01632             We are using only a prefix of the column as a key:
01633             Create a new field for the key part that matches the index
01634           */
01635           local_field= key_part->field= local_field->new_field(&outparam.mem(), &outparam, 0);
01636           local_field->field_length= key_part->length;
01637         }
01638       }
01639     }
01640   }
01641 
01642   /* Allocate bitmaps */
01643 
01644   outparam.def_read_set.resize(_field_size);
01645   outparam.def_write_set.resize(_field_size);
01646   outparam.tmp_set.resize(_field_size);
01647   outparam.default_column_bitmaps();
01648 
01649   return 0;
01650 }
01651 
01652 int TableShare::open_table_cursor_inner(const identifier::Table &identifier,
01653                                         uint32_t db_stat, uint32_t ha_open_flags,
01654                                         Table &outparam,
01655                                         bool &error_reported)
01656 {
01657   /* The table struct is now initialized;  Open the table */
01658   int local_error= 2;
01659   if (db_stat)
01660   {
01661     assert(!(db_stat & HA_WAIT_IF_LOCKED));
01662     int ha_err;
01663 
01664     if ((ha_err= (outparam.cursor->ha_open(identifier,
01665                                            (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
01666                                            (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE : HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags))))
01667     {
01668       switch (ha_err)
01669       {
01670       case HA_ERR_NO_SUCH_TABLE:
01671         /*
01672           The table did not exists in storage engine, use same error message
01673           as if the .frm cursor didn't exist
01674         */
01675         local_error= 1;
01676         errno= ENOENT;
01677         break;
01678       case EMFILE:
01679         /*
01680           Too many files opened, use same error message as if the .frm
01681           cursor can't open
01682         */
01683         local_error= 1;
01684         errno= EMFILE;
01685         break;
01686       default:
01687         outparam.print_error(ha_err, MYF(0));
01688         error_reported= true;
01689         if (ha_err == HA_ERR_TABLE_DEF_CHANGED)
01690           local_error= 7;
01691         break;
01692       }
01693       return local_error;
01694     }
01695   }
01696 
01697   return 0;
01698 }
01699 
01700 /* error message when opening a form cursor */
01701 void TableShare::open_table_error(int pass_error, int db_errno, int pass_errarg)
01702 {
01703   char buff[FN_REFLEN];
01704   myf errortype= ME_ERROR+ME_WAITTANG;
01705 
01706   switch (pass_error) {
01707   case 7:
01708   case 1:
01709     if (db_errno == ENOENT)
01710     {
01711       identifier::Table identifier(db.data(), table_name.data());
01712       my_error(ER_TABLE_UNKNOWN, identifier);
01713     }
01714     else
01715     {
01716       snprintf(buff, sizeof(buff), "%s",normalized_path.data());
01717       my_error((db_errno == EMFILE) ? ER_CANT_OPEN_FILE : ER_FILE_NOT_FOUND, errortype, buff, db_errno);
01718     }
01719     break;
01720   case 2:
01721     {
01722       drizzled::error_t err_no= (db_errno == ENOENT) ? ER_FILE_NOT_FOUND : (db_errno == EAGAIN) ? ER_FILE_USED : ER_CANT_OPEN_FILE;
01723       my_error(err_no, errortype, normalized_path.data(), db_errno);
01724       break;
01725     }
01726   case 5:
01727     {
01728       const char *csname= get_charset_name((uint32_t) pass_errarg);
01729       char tmp[10];
01730       if (!csname || csname[0] =='?')
01731       {
01732         snprintf(tmp, sizeof(tmp), "#%d", pass_errarg);
01733         csname= tmp;
01734       }
01735       my_printf_error(ER_UNKNOWN_COLLATION, _("Unknown collation '%s' in table '%-.64s' definition"), MYF(0), csname, table_name.data());
01736       break;
01737     }
01738   case 6:
01739     snprintf(buff, sizeof(buff), "%s", normalized_path.data());
01740     my_printf_error(ER_NOT_FORM_FILE, _("Table '%-.64s' was created with a different version of Drizzle and cannot be read"), MYF(0), buff);
01741     break;
01742   case 8:
01743     break;
01744   default:        /* Better wrong error than none */
01745   case 4:
01746     snprintf(buff, sizeof(buff), "%s", normalized_path.data());
01747     my_error(ER_NOT_FORM_FILE, errortype, buff, 0);
01748     break;
01749   }
01750   return;
01751 } /* open_table_error */
01752 
01753 Field *TableShare::make_field(const message::Table::Field &pfield,
01754                               unsigned char *ptr,
01755                               uint32_t field_length,
01756                               bool is_nullable,
01757                               unsigned char *null_pos,
01758                               unsigned char null_bit,
01759                               uint8_t decimals,
01760                               enum_field_types field_type,
01761                               const charset_info_st * field_charset,
01762                               Field::utype unireg_check,
01763                               TYPELIB *interval,
01764                               const char *field_name)
01765 {
01766   return make_field(pfield,
01767                     ptr,
01768                     field_length,
01769                     is_nullable,
01770                     null_pos,
01771                     null_bit,
01772                     decimals,
01773                     field_type,
01774                     field_charset,
01775                     unireg_check,
01776                     interval,
01777                     field_name,
01778                     pfield.constraints().is_unsigned());
01779 }
01780 
01781 Field *TableShare::make_field(const message::Table::Field &,
01782                               unsigned char *ptr,
01783                               uint32_t field_length,
01784                               bool is_nullable,
01785                               unsigned char *null_pos,
01786                               unsigned char null_bit,
01787                               uint8_t decimals,
01788                               enum_field_types field_type,
01789                               const charset_info_st * field_charset,
01790                               Field::utype unireg_check,
01791                               TYPELIB *interval,
01792                               const char *field_name, 
01793                               bool is_unsigned)
01794 {
01795   if (! is_nullable)
01796   {
01797     null_pos=0;
01798     null_bit=0;
01799   }
01800   else
01801   {
01802     null_bit= ((unsigned char) 1) << null_bit;
01803   }
01804 
01805   switch (field_type)
01806   {
01807   case DRIZZLE_TYPE_ENUM:
01808     return new (&mem_root) Field_enum(ptr,
01809                                       field_length,
01810                                       null_pos,
01811                                       null_bit,
01812                                       field_name,
01813                                       interval,
01814                                       field_charset);
01815   case DRIZZLE_TYPE_VARCHAR:
01816     setVariableWidth();
01817     return new (&mem_root) Field_varstring(ptr,field_length,
01818                                       ha_varchar_packlength(field_length),
01819                                       null_pos,null_bit,
01820                                       field_name,
01821                                       field_charset);
01822   case DRIZZLE_TYPE_BLOB:
01823     return new (&mem_root) Field_blob(ptr,
01824                                       null_pos,
01825                                       null_bit,
01826                                       field_name,
01827                                       this,
01828                                       field_charset);
01829   case DRIZZLE_TYPE_DECIMAL:
01830     return new (&mem_root) Field_decimal(ptr,
01831                                          field_length,
01832                                          null_pos,
01833                                          null_bit,
01834                                          unireg_check,
01835                                          field_name,
01836                                          decimals);
01837   case DRIZZLE_TYPE_DOUBLE:
01838     return new (&mem_root) Field_double(ptr,
01839                                    field_length,
01840                                    null_pos,
01841                                    null_bit,
01842                                    unireg_check,
01843                                    field_name,
01844                                    decimals,
01845                                    false,
01846                                    false /* is_unsigned */);
01847   case DRIZZLE_TYPE_UUID:
01848     return new (&mem_root) field::Uuid(ptr,
01849                                        field_length,
01850                                        null_pos,
01851                                        null_bit,
01852                                        field_name);
01853   case DRIZZLE_TYPE_IPV6:
01854     return new (&mem_root) field::IPv6(ptr,
01855                                        field_length,
01856                                        null_pos,
01857                                        null_bit,
01858                                        field_name);
01859   case DRIZZLE_TYPE_BOOLEAN:
01860     return new (&mem_root) field::Boolean(ptr,
01861                                           field_length,
01862                                           null_pos,
01863                                           null_bit,
01864                                           field_name,
01865                                           is_unsigned);
01866   case DRIZZLE_TYPE_LONG:
01867     return new (&mem_root) field::Int32(ptr,
01868                                         field_length,
01869                                         null_pos,
01870                                         null_bit,
01871                                         unireg_check,
01872                                         field_name);
01873   case DRIZZLE_TYPE_LONGLONG:
01874     {
01875       if (is_unsigned)
01876       {
01877         return new (&mem_root) field::Size(ptr,
01878                                            field_length,
01879                                            null_pos,
01880                                            null_bit,
01881                                            unireg_check,
01882                                            field_name);
01883       }
01884 
01885       return new (&mem_root) field::Int64(ptr,
01886                                           field_length,
01887                                           null_pos,
01888                                           null_bit,
01889                                           unireg_check,
01890                                           field_name);
01891     }
01892   case DRIZZLE_TYPE_MICROTIME:
01893     return new (&mem_root) field::Microtime(ptr,
01894                                             null_pos,
01895                                             null_bit,
01896                                             unireg_check,
01897                                             field_name,
01898                                             this);
01899   case DRIZZLE_TYPE_TIMESTAMP:
01900     return new (&mem_root) field::Epoch(ptr,
01901                                         null_pos,
01902                                         null_bit,
01903                                         unireg_check,
01904                                         field_name,
01905                                         this);
01906   case DRIZZLE_TYPE_TIME:
01907     return new (&mem_root) field::Time(ptr, field_length, null_pos, null_bit, field_name);
01908   case DRIZZLE_TYPE_DATE:
01909     return new (&mem_root) Field_date(ptr, null_pos, null_bit, field_name);
01910   case DRIZZLE_TYPE_DATETIME:
01911     return new (&mem_root) Field_datetime(ptr, null_pos, null_bit, field_name);
01912   case DRIZZLE_TYPE_NULL:
01913     return new (&mem_root) Field_null(ptr, field_length, field_name);
01914   }
01915   assert(false);
01916   abort();
01917 }
01918 
01919 void TableShare::refreshVersion()
01920 {
01921   version= g_refresh_version;
01922 }
01923 
01924 
01925 } /* namespace drizzled */