open_binary_frm

static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
                           File file)
{
  int error, errarg= 0;
  uint new_frm_ver, field_pack_length, new_field_pack_flag;
  uint interval_count, interval_parts, read_length, int_length;
  uint db_create_options, keys, key_parts, n_length;
  uint key_info_length, com_length, null_bit_pos;
  uint extra_rec_buf_length;
  uint i,j;
  bool use_hash;
  char *keynames, *names, *comment_pos;
  uchar forminfo[288];
  uchar *record;
  uchar *disk_buff, *strpos, *null_flags, *null_pos;
  ulong pos, record_offset, *rec_per_key, rec_buff_length;
  handler *handler_file= 0;
  KEY    *keyinfo;
  KEY_PART_INFO *key_part;
  SQL_CRYPT *crypted=0;
  Field  **field_ptr, *reg_field;
  const char **interval_array;
  enum legacy_db_type legacy_db_type;
  my_bitmap_map *bitmaps;
  uchar *extra_segment_buff= 0;
  const uint format_section_header_size= 8;
  uchar *format_section_fields= 0;
  DBUG_ENTER("open_binary_frm");

  new_field_pack_flag= head[27];
  new_frm_ver= (head[2] - FRM_VER);
  field_pack_length= new_frm_ver < 2 ? 11 : 17;
  disk_buff= 0;

  error= 3;
  /* Position of the form in the form file. */
  if (!(pos= get_form_pos(file, head)))
    goto err;                                   /* purecov: inspected */

  mysql_file_seek(file,pos,MY_SEEK_SET,MYF(0));
  if (mysql_file_read(file, forminfo,288,MYF(MY_NABP)))
    goto err;
  share->frm_version= head[2];
  /*
    Check if .frm file created by MySQL 5.0. In this case we want to
    display CHAR fields as CHAR and not as VARCHAR.
    We do it this way as we want to keep the old frm version to enable
    MySQL 4.1 to read these files.
  */
  if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && head[33] == 5)
    share->frm_version= FRM_VER_TRUE_VARCHAR;

  legacy_db_type= (enum legacy_db_type) (uint) *(head+3);
  DBUG_ASSERT(share->db_plugin == NULL);

  share->db_create_options= db_create_options= uint2korr(head+30);
  share->db_options_in_use= share->db_create_options;
  share->mysql_version= uint4korr(head+51);
  share->null_field_first= 0;

  share->max_rows= uint4korr(head+18);
  share->min_rows= uint4korr(head+22);

  /* Read keyinformation */
  key_info_length= (uint) uint2korr(head+28);
  mysql_file_seek(file, (ulong) uint2korr(head+6), MY_SEEK_SET, MYF(0));

  /**   *disk_buff已经被分配了内存,大小为key_info_length   */
  if (read_string(file,(uchar**) &disk_buff,key_info_length))
    goto err;                                   /* purecov: inspected */
  if (disk_buff[0] & 0x80)
  {
    share->keys=      keys=      (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
    share->key_parts= key_parts= uint2korr(disk_buff+2);
  }
  else
  {
    share->keys=      keys=      disk_buff[0];
    share->key_parts= key_parts= disk_buff[1];
  }

  n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO);
  if (!(keyinfo = (KEY*) alloc_root(&share->mem_root,n_length + uint2korr(disk_buff+4))))
    goto err;
  bzero((char*) keyinfo,n_length);

  /**   *share->key_info代表keyinfo这段内存起始地址   *keyinfo的类型为KEY*,故keyinfo++,意味着数组递增   *   */
  share->key_info= keyinfo;
  key_part= reinterpret_cast<KEY_PART_INFO*>(keyinfo+keys);
  strpos=disk_buff+6;

  if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root,
                                         sizeof(ulong)*key_parts)))
    goto err;

  for (i=0 ; i < keys ; i++, keyinfo++)
  {
    keyinfo->table= 0;                           // Updated in open_frm
    if (new_frm_ver >= 3)
    {
      keyinfo->flags=       (uint) uint2korr(strpos) ^ HA_NOSAME;      //索引长度,索引中列的个数
      keyinfo->key_length= (uint) uint2korr(strpos+2);
      keyinfo->key_parts=  (uint) strpos[4];
      keyinfo->algorithm=  (enum ha_key_alg) strpos[5];
      keyinfo->block_size= uint2korr(strpos+6);
      strpos+=8;
    }

    keyinfo->key_part=     key_part;
    keyinfo->rec_per_key= rec_per_key;
    for (j=keyinfo->key_parts ; j-- ; key_part++)
    {
      *rec_per_key++=0;
      key_part->fieldnr=    (uint16) (uint2korr(strpos) & FIELD_NR_MASK);
      key_part->offset= (uint) uint2korr(strpos+2)-1;
      key_part->key_type=    (uint) uint2korr(strpos+5);
    }
  }
  keynames=(char*) key_part;
  strpos+= (strmov(keynames, (char *) strpos) - keynames)+1;

  //reading index comments
  for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
  {
    if (keyinfo->flags & HA_USES_COMMENT)
    {
      keyinfo->comment.length= uint2korr(strpos);
      keyinfo->comment.str= strmake_root(&share->mem_root, (char*) strpos+2,
                                         keyinfo->comment.length);
      strpos+= 2 + keyinfo->comment.length;
    }
  }

  share->key_block_size= uint2korr(head+62);

  share->fields= uint2korr(forminfo+258);
  pos= uint2korr(forminfo+260);   /* Length of all screens */
  n_length= uint2korr(forminfo+268);

  share->null_fields= uint2korr(forminfo+282);
  com_length= uint2korr(forminfo+284);
if (!(field_ptr = (Field **)
    alloc_root(&share->mem_root,
           (uint) ((share->fields+1)*sizeof(Field*)+
               interval_count*sizeof(TYPELIB)+
               (share->fields+interval_parts+
                keys+3)*sizeof(char *)+
               (n_length+int_length+com_length)))))
    goto err;                                   /* purecov: inspected */
    /**   *field_ptr也是刚分配内存的起始地址,赋值给share->field   */
  share->field= field_ptr;
  read_length=(uint) (share->fields * field_pack_length +
              pos+ (uint) (n_length+int_length+com_length));
  if (read_string(file,(uchar**) &disk_buff,read_length))
    goto err;                                   /* purecov: inspected */
  strpos= disk_buff+pos;

if (keynames)
    fix_type_pointers(&interval_array, &share->keynames, 1, &keynames);

 /* Allocate handler */
  if (!(handler_file= get_new_handler(share, thd->mem_root,
                                      share->db_type())))
    goto err;

  record= share->default_values-1;              /* Fieldstart = 1 */
  if (share->null_field_first)
  {
    null_flags= null_pos= (uchar*) record+1;
    null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
    /*
      null_bytes below is only correct under the condition that
      there are no bit fields.  Correct values is set below after the
      table struct is initialized
    */
    share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8;
  }
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
  {
    uint pack_flag, interval_nr, unireg_type, recpos, field_length;
    enum_field_types field_type;
    CHARSET_INFO *charset=NULL;
    Field::geometry_type geom_type= Field::GEOM_GEOMETRY;
    LEX_STRING comment;

    if (new_frm_ver >= 3)
    {
      /* new frm file in 4.1 */
      field_length= uint2korr(strpos+3);
      recpos=        uint3korr(strpos+5);
      pack_flag=    uint2korr(strpos+8);
      unireg_type=  (uint) strpos[10];
      interval_nr=  (uint) strpos[12];
      uint comment_length=uint2korr(strpos+15);
      field_type=(enum_field_types) (uint) strpos[13];

    }

    /**     *这里的field_ptr其实是个FIELD*的对象     */
    *field_ptr= reg_field=
      make_field(share, record+recpos,
         (uint32) field_length,
         null_pos, null_bit_pos,
         pack_flag,
         field_type,
         charset,
         geom_type,
         (Field::utype) MTYP_TYPENR(unireg_type),
         (interval_nr ?
          share->intervals+interval_nr-1 :
          (TYPELIB*) 0),
         share->fieldnames.type_names[i]);

  }//循环结束
  *field_ptr=0;                    // End marker

  /* Fix key->name and key_part->field */
  if (key_parts)
  {
    uint primary_key=(uint) (find_type(primary_key_name, &share->keynames,
                                       FIND_TYPE_NO_PREFIX) - 1);
    longlong ha_option= handler_file->ha_table_flags();
    keyinfo= share->key_info;
    key_part= keyinfo->key_part;
        /**     *share->keys本身是个结构体数组,     *里面每一个key,设置其name,     *key中的key_part也是个结构体数组,其中的filednr为share->filed该数组中的下标     *     */
    for (uint key=0 ; key < share->keys ; key++,keyinfo++)
    {
      uint usable_parts= 0;
      keyinfo->name=(char*) share->keynames.type_names[key];
     for (i=0 ; i < keyinfo->key_parts ; key_part++,i++)
      {
        Field *field;

        key_part->fieldnr= (uint16) find_field(share->field,share->default_values,(uint) key_part->offset,(uint)                   key_part->length);

        field= key_part->field= share->field[key_part->fieldnr-1];
        key_part->type= field->key_type();
        if (field->null_ptr)
        {
          key_part->null_offset=(uint) ((uchar*) field->null_ptr -
                                        share->default_values);
          key_part->null_bit= field->null_bit;
          key_part->store_length+=HA_KEY_NULL_LENGTH;
          keyinfo->flags|=HA_NULL_PART_KEY;
          keyinfo->extra_length+= HA_KEY_NULL_LENGTH;
          keyinfo->key_length+= HA_KEY_NULL_LENGTH;
        }

      }

      share->total_key_length+= keyinfo->key_length;

    }

  }
/*
    the correct null_bytes can now be set, since bitfields have been taken
    into account
  */
  share->null_bytes= (null_pos - (uchar*) null_flags +
                      (null_bit_pos + 7) / 8);
  share->last_null_bit_pos= null_bit_pos;

  share->db_low_byte_first= handler_file->low_byte_first();
  share->column_bitmap_size= bitmap_buffer_size(share->fields);

  if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root,
                                             share->column_bitmap_size)))
    goto err;
  bitmap_init(&share->all_set, bitmaps, share->fields, FALSE);
  bitmap_set_all(&share->all_set);

  delete handler_file;
#ifndef DBUG_OFF
  if (use_hash)
    (void) my_hash_check(&share->name_hash);
#endif
  my_free(extra_segment_buff);
  DBUG_RETURN (0);

 err:
  share->error= error;
  share->open_errno= my_errno;
  share->errarg= errarg;
  my_free(disk_buff);
  my_free(extra_segment_buff);
  delete crypted;
  delete handler_file;
  my_hash_free(&share->name_hash);
  if (share->ha_data_destroy)
  {
    share->ha_data_destroy(share->ha_data);
    share->ha_data_destroy= NULL;
  }
#ifdef WITH_PARTITION_STORAGE_ENGINE
  if (share->ha_part_data_destroy)
  {
    share->ha_part_data_destroy(share->ha_part_data);
    share->ha_data_destroy= NULL;
  }
#endif /* WITH_PARTITION_STORAGE_ENGINE */

  open_table_error(share, error, share->open_errno, errarg);
  DBUG_RETURN(error);
} /* open_binary_frm */
时间: 2024-10-08 17:25:06

open_binary_frm的相关文章

Innodb加载数据字典 &amp;&amp; flush tables

测试了两个case,属于之前blog的遗留问题: innodb如何加载数据字典 flush tables都做了什么操作 先来看下innodb加载数据字典: 首次使用:select * from tt; 1. 创建handler对象 函数调用栈: open_binary_frm get_new_handler innobase_create_handler ha_innobase::ha_innobase 根据单实例 handlerton + table_share两个参数,创建了handler对

mysql 从源码解读.frm文件构成

Mysql的.frm文件是用于保存表结构信息的文件,最近从源码了解了一下.frm的组成,在网上也有一些大神对.frm的组成做过分享,自己再去了解一下总是没坏处的,.frm文件的创建在create_frm函数,但是这个函数只有对header部分的记录信息,具体表结构信息未找到在哪个函数生成的,不过有个open_binary_frm函数是对.frm文件的读取可以了解.frm的详细结构组成,注意下面的函数都是从5.7.19的版本中提取,5.7之前的版本可能有点不同,比如虚拟列 首先看看create_f