http://www.cnblogs.com/jiangxu67/p/4755097.html
http://www.cnblogs.com/jiangxu67/p/4755097.html
http://guduwhuzhe.iteye.com/blog/1887619
bool mysql_create_frm(THD *thd, const char *file_name, const char *db, const char *table, HA_CREATE_INFO *create_info, List<Create_field> &create_fields, uint keys, KEY *key_info, handler *db_file) { LEX_STRING str_db_type; uint reclength, info_length, screens, key_info_length, maxlength, tmp_len, i; ulong key_buff_length; File file; ulong filepos, data_offset; uchar fileinfo[],forminfo[],*keybuff; uchar *screen_buff; ]; Pack_header_error_handler pack_header_error_handler; int error; ; uint format_section_length; ; DBUG_ENTER("mysql_create_frm"); DBUG_ASSERT(*fn_rext((char*)file_name)); // Check .frm extension ))) DBUG_RETURN(); DBUG_ASSERT(db_file != NULL); /* If fixed row records, we need one bit to check for deleted rows */ if (!(create_info->table_options & HA_OPTION_PACK_RECORD)) create_info->null_bits++; data_offset= (create_info->null_bits + ) / ; thd->push_internal_handler(&pack_header_error_handler); error= pack_header(forminfo, ha_legacy_type(create_info->db_type), create_fields,info_length, screens, create_info->table_options, data_offset, db_file); thd->pop_internal_handler(); if (error) { my_free(screen_buff); } reclength=uint2korr(forminfo+); /* Calculate extra data segment length */ str_db_type.str= (char *) ha_resolve_storage_engine_name(create_info->db_type); str_db_type.length= strlen(str_db_type.str); /* str_db_type */ create_info->extra_size= ( + str_db_type.length + + create_info->connect_string.length); create_info->extra_size+= ; /* If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes, store the comment in an extra segment (up to TABLE_COMMENT_MAXLEN bytes). Pre 6.0, the limit was 60 characters, with no extra segment-handling. */ if (create_info->comment.length > TABLE_COMMENT_INLINE_MAXLEN) { forminfo[]=; create_info->extra_size+= + create_info->comment.length; } else{ strmake((, create_info->comment.str ? create_info->comment.str : "", create_info->comment.length); forminfo[]=(uchar) create_info->comment.length; } if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo, create_info, keys, key_info)) < ) { my_free(screen_buff); DBUG_RETURN(); } key_buff_length= uint4korr(fileinfo+); keybuff=(uchar*) my_malloc(key_buff_length, MYF()); key_info_length= pack_keys(keybuff, keys, key_info, data_offset); /* Ensure that there are no forms in this newly created form file. Even if the form file exists, create_frm must truncate it to ensure one form per form file. */ DBUG_ASSERT(uint2korr(fileinfo+) == ); if (!(filepos= make_new_entry(file, fileinfo, NULL, ""))) goto err; maxlength=()); int2store(forminfo+,maxlength); int4store(fileinfo+,(ulong) (filepos+maxlength)); fileinfo[]= (uchar) test((create_info->max_rows == ) && (create_info->min_rows == ) && (keys == )); int2store(fileinfo+,key_info_length); int2store(fileinfo+,db_file->extra_rec_buf_length()); , 0L, MYF_RW) || mysql_file_pwrite(file, keybuff, key_info_length, (), MYF_RW)) goto err; mysql_file_seek(file, () + (ulong) key_buff_length, MY_SEEK_SET, MYF()); if (make_empty_rec(thd,file,ha_legacy_type(create_info->db_type), create_info->table_options, create_fields,reclength, data_offset, db_file)) goto err; int2store(buff, create_info->connect_string.length); , MYF(MY_NABP)) || mysql_file_write(file, (const uchar*)create_info->connect_string.str, create_info->connect_string.length, MYF(MY_NABP))) goto err; int2store(buff, str_db_type.length); , MYF(MY_NABP)) || mysql_file_write(file, (const uchar*)str_db_type.str, str_db_type.length, MYF(MY_NABP))) goto err; { bzero((uchar*) buff, ); , MYF_RW)) goto err; } ; i < keys; i++) { if (key_info[i].parser_name) { if (mysql_file_write(file, (const uchar*)key_info[i].parser_name->str, key_info[i].parser_name->length + , MYF(MY_NABP))) goto err; } } ] == (uchar)) { uchar comment_length_buff[]; int2store(comment_length_buff,create_info->comment.length); , MYF(MY_NABP)) || mysql_file_write(file, (uchar*) create_info->comment.str, create_info->comment.length, MYF(MY_NABP))) goto err; } /* "Format section" with additional table and column properties */ mysql_file_seek(file, filepos, MY_SEEK_SET, MYF()); , MYF_RW) || mysql_file_write(file, screen_buff, info_length, MYF_RW) || pack_fields(file, create_fields, data_offset)) goto err; my_free(screen_buff); my_free(keybuff); if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) && (mysql_file_sync(file, MYF(MY_WME)) || my_sync_dir_by_file(file_name, MYF(MY_WME)))) goto err2; if (mysql_file_close(file, MYF(MY_WME))) goto err3; err: my_free(screen_buff); my_free(keybuff); err2: (void) mysql_file_close(file, MYF(MY_WME)); err3: mysql_file_delete(key_file_frm, file_name, MYF()); DBUG_RETURN(); } /* mysql_create_frm */
/* Pack keyinfo and keynames to keybuff for save in form-file. */ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo, ulong data_offset) { uint key_parts,length; uchar *pos, *keyname_pos; KEY *key,*end; KEY_PART_INFO *key_part,*key_part_end; DBUG_ENTER("pack_keys"); pos=keybuff+; key_parts=; for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++) { int2store(pos, (key->flags ^ HA_NOSAME)); int2store(pos+,key->key_length); pos[]= (uchar) key->key_parts; pos[]= (uchar) key->algorithm; int2store(pos+, key->block_size); pos+=; key_parts+=key->key_parts; DBUG_PRINT("loop", ("flags: %lu key_parts: %d at 0x%lx", key->flags, key->key_parts, (long) key->key_part)); for (key_part=key->key_part,key_part_end=key_part+key->key_parts ; key_part != key_part_end ; key_part++) { uint offset; DBUG_PRINT("loop",("field: %d startpos: %lu length: %d", key_part->fieldnr, key_part->offset + data_offset, key_part->length)); int2store(pos,key_part->fieldnr++FIELD_NAME_USED); offset= (); int2store(pos+, offset); pos[]=; // Sort order int2store(pos+,key_part->key_type); int2store(pos+,key_part->length); pos+=; } } /* Save keynames */ keyname_pos=pos; *pos++=(uchar) NAMES_SEP_CHAR; for (key=keyinfo ; key != end ; key++) { uchar *tmp=(uchar*) strmov((char*) pos,key->name); *tmp++= (uchar) NAMES_SEP_CHAR; *tmp=; pos=tmp; } *(pos++)=; for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++) { if (key->flags & HA_USES_COMMENT) { int2store(pos, key->comment.length); uchar *tmp= (uchar*)strnmov((,key->comment.str, key->comment.length); pos= tmp; } } || key_parts > ) { keybuff[]= (key_count & 0x7f) | 0x80; keybuff[]= key_count >> ; int2store(keybuff+,key_parts); } else { keybuff[]=(uchar) key_count; keybuff[]=(uchar) key_parts; keybuff[]= keybuff[]= ; } length=(uint) (pos-keyname_pos); int2store(keybuff+,length); DBUG_RETURN((uint) (pos-keybuff)); } /* pack_keys */
/* Save fields, fieldnames and intervals */ static bool pack_fields(File file, List<Create_field> &create_fields, ulong data_offset) { reg2 uint i; ; uchar buff[MAX_FIELD_WIDTH]; Create_field *field; DBUG_ENTER("pack_fields"); /* Write field info */ List_iterator<Create_field> it(create_fields); int_count=; while ((field=it++)) { uint recpos; buff[]= (uchar) field->row; buff[]= (uchar) field->col; buff[]= (uchar) field->sc_length; int2store(buff+, field->length); /* The +1 is here becasue the col offset in .frm file have offset 1 */ recpos= field->offset+ + (uint) data_offset; int3store(buff+,recpos); int2store(buff+,field->pack_flag); DBUG_ASSERT(field->unireg_check < ); buff[]= (uchar) field->unireg_check; buff[]= (uchar) field->interval_id; buff[]= (uchar) field->sql_type; if (field->sql_type == MYSQL_TYPE_GEOMETRY) { buff[]= ; buff[]= (uchar) field->geom_type; #ifndef HAVE_SPATIAL DBUG_ASSERT(); // Should newer happen #endif } else if (field->charset) { buff[]= (uchar) (field->charset->number >> ); buff[]= (uchar) field->charset->number; } else { buff[]= buff[]= ; // Numerical } int2store(buff+, field->comment.length); comment_length+= field->comment.length; set_if_bigger(int_count,field->interval_id); if (mysql_file_write(file, buff, FCOMP, MYF_RW)) DBUG_RETURN(); } /* Write fieldnames */ buff[]=(uchar) NAMES_SEP_CHAR; , MYF_RW)) DBUG_RETURN(); i=; it.rewind(); while ((field=it++)) { char *pos= strmov((char*) buff,field->field_name); *pos++=NAMES_SEP_CHAR; ) *pos++=; if (mysql_file_write(file, buff, (size_t) (pos-(char*) buff), MYF_RW)) DBUG_RETURN(); i++; } /* Write intervals */ if (int_count) { String tmp((char*) buff,sizeof(buff), &my_charset_bin); tmp.length(); it.rewind(); int_count=; while ((field=it++)) { if (field->interval_id > int_count) { unsigned ; unsigned ]; uint i; unsigned char *val= NULL; bzero(occ, sizeof(occ)); ; (val= (unsigned char*) field->interval->type_names[i]); i++) ; j < field->interval->type_lengths[i]; j++) occ[(unsigned ; if (!occ[(unsigned char)NAMES_SEP_CHAR]) sep= (unsigned char) NAMES_SEP_CHAR; else if (!occ[(unsigned int)',']) sep= ','; else { ; i<; i++) { if(!occ[i]) { sep= i; break; } } if(!sep) /* disaster, enum uses all characters, none left as separator */ { my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS), MYF()); DBUG_RETURN(); } } int_count= field->interval_id; tmp.append(sep); for (const char **pos=field->interval->type_names ; *pos ; pos++) { tmp.append(*pos); tmp.append(sep); } tmp.append('\0'); // End of intervall } } if (mysql_file_write(file, (uchar*) tmp.ptr(), tmp.length(), MYF_RW)) DBUG_RETURN(); } if (comment_length) { it.rewind(); int_count=; while ((field=it++)) { if (field->comment.length) if (mysql_file_write(file, (uchar*) field->comment.str, field->comment.length, MYF_RW)) DBUG_RETURN(); } } DBUG_RETURN(); }