参数uchar* head 是已经分配好内存的64个字节的地址
http://mysql.taobao.org/monthly/2015/08/07/
/**
*先从.frm文件读取64字节
*第28和第29字节记录了key_length
*
*利用lseek定位到第30字节,并读取key_length长度的信息到disk_buff中
*disk_buff[0]代表了索引的个数 keys_num
*disk_buff[1]代表了索引中列的个数 key_parts_num
*
*为了把disk_buff中的信息copy到结构体中,还要分配 keys*sizeof(KEY)+key_parts*sizeof(KEY_PARTS_INFO)大小的内存 key_buff,类型为KEY*
*
*
*做循环
*share->key_info=key_buff;
*key_part = key_buff+keys_num;
* for(int i=0;i<keys;key_buff++)
key_buff->key_length=xxx;
xxxxx
key_buf->key_part = key_part;
for(j=key_buff->key_parts;j>=0;j--,key_part++)
key_part->fieldnr=xxx
*
*share->field = field_ptr //field_ptr为新分配的内存
*share->fileds = xxx;
* for(int i=0;i<xxx;field_ptr++ )
* field_ptr=xxx;
*
*/
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]; 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]; } /**
*因为keyinfo是MYSQL服务器这边的结构体,因此需要分配内存
*/ 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; 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 */