make the open_table_def to read the whole frm in memory
and let open_binary_frm to parse it from the buffer, not a file. this avoids jumping back in forth in the frm file, and doing intermediate buffer mallocs.
This commit is contained in:
parent
03dfb2c121
commit
0d1a595875
197
sql/table.cc
197
sql/table.cc
@ -65,18 +65,13 @@ LEX_STRING parse_vcol_keyword= { C_STRING_WITH_LEN("PARSE_VCOL_EXPR ") };
|
||||
|
||||
/* Functions defined in this file */
|
||||
|
||||
void open_table_error(TABLE_SHARE *share, int error, int db_errno,
|
||||
myf errortype, int errarg);
|
||||
static int open_binary_frm(THD *thd, TABLE_SHARE *share,
|
||||
uchar *head, File file);
|
||||
static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *buf);
|
||||
static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
|
||||
uint types, char **names);
|
||||
static uint find_field(Field **fields, uchar *record, uint start, uint length);
|
||||
|
||||
inline bool is_system_table_name(const char *name, uint length);
|
||||
|
||||
static ulong get_form_pos(File file, uchar *head);
|
||||
|
||||
/**************************************************************************
|
||||
Object_creation_ctx implementation.
|
||||
**************************************************************************/
|
||||
@ -691,7 +686,7 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags)
|
||||
}
|
||||
|
||||
error= 4;
|
||||
if (mysql_file_read(file, head, 64, MYF(MY_NABP)))
|
||||
if (mysql_file_read(file, head, sizeof(head), MYF(MY_NABP)))
|
||||
goto err;
|
||||
|
||||
if (head[0] == (uchar) 254 && head[1] == 1)
|
||||
@ -730,12 +725,32 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags)
|
||||
/* No handling of text based files yet */
|
||||
if (table_type == 1)
|
||||
{
|
||||
MY_STAT stats;
|
||||
uchar *buf;
|
||||
|
||||
if (my_fstat(file, &stats, MYF(0)))
|
||||
goto err;
|
||||
|
||||
if (!(buf= (uchar*)my_malloc(stats.st_size, MYF(MY_THREAD_SPECIFIC|MY_WME))))
|
||||
goto err;
|
||||
|
||||
memcpy(buf, head, sizeof(head));
|
||||
|
||||
if (mysql_file_read(file, buf + sizeof(head),
|
||||
stats.st_size - sizeof(head), MYF(MY_NABP)))
|
||||
{
|
||||
my_free(buf);
|
||||
goto err;
|
||||
}
|
||||
mysql_file_close(file, MYF(MY_WME));
|
||||
|
||||
root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
|
||||
old_root= *root_ptr;
|
||||
*root_ptr= &share->mem_root;
|
||||
error= open_binary_frm(thd, share, head, file);
|
||||
error= open_binary_frm(thd, share, buf);
|
||||
*root_ptr= old_root;
|
||||
error_given= 1;
|
||||
my_free(buf);
|
||||
}
|
||||
|
||||
share->table_category= get_table_category(& share->db, & share->table_name);
|
||||
@ -743,6 +758,8 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags)
|
||||
if (!error)
|
||||
thd->status_var.opened_shares++;
|
||||
|
||||
DBUG_RETURN(error);
|
||||
|
||||
err:
|
||||
mysql_file_close(file, MYF(MY_WME));
|
||||
|
||||
@ -757,23 +774,30 @@ err_not_open:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE
|
||||
/**
|
||||
Read data from a binary .frm file image into a TABLE_SHARE
|
||||
|
||||
@note
|
||||
frm bytes at the following offsets are unused in MariaDB 10.0:
|
||||
|
||||
8..9 (used to be the number of "form names")
|
||||
28..29 (used to be key_info_length)
|
||||
|
||||
They're still set, for compatibility reasons, but never read.
|
||||
*/
|
||||
|
||||
static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
File file)
|
||||
static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *frm_image)
|
||||
{
|
||||
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 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 *forminfo;
|
||||
uchar *record;
|
||||
uchar *disk_buff, *strpos, *null_flags, *null_pos;
|
||||
ulong pos, record_offset;
|
||||
@ -791,7 +815,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
uint vcol_screen_length, UNINIT_VAR(options_len);
|
||||
char *vcol_screen_pos;
|
||||
uchar *UNINIT_VAR(options);
|
||||
uchar *extra_segment_buff= 0;
|
||||
KEY first_keyinfo;
|
||||
uint len;
|
||||
KEY_PART_INFO *first_key_part= NULL;
|
||||
@ -801,37 +824,36 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
share->ext_key_parts= 0;
|
||||
DBUG_ENTER("open_binary_frm");
|
||||
|
||||
new_field_pack_flag= head[27];
|
||||
new_frm_ver= (head[2] - FRM_VER);
|
||||
new_field_pack_flag= frm_image[27];
|
||||
new_frm_ver= (frm_image[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)))
|
||||
/* Position of the form in the form file. */
|
||||
len = uint2korr(frm_image+4);
|
||||
if (!(pos= uint4korr(frm_image + 64 + len)))
|
||||
goto err;
|
||||
share->frm_version= head[2];
|
||||
|
||||
forminfo= frm_image + pos;
|
||||
share->frm_version= frm_image[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)
|
||||
if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && frm_image[33] == 5)
|
||||
share->frm_version= FRM_VER_TRUE_VARCHAR;
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (*(head+61) &&
|
||||
if (*(frm_image+61) &&
|
||||
!(share->default_part_db_type=
|
||||
ha_checktype(thd, (enum legacy_db_type) (uint) *(head+61), 1, 0)))
|
||||
ha_checktype(thd, (enum legacy_db_type) (uint) *(frm_image+61), 1, 0)))
|
||||
goto err;
|
||||
DBUG_PRINT("info", ("default_part_db_type = %u", head[61]));
|
||||
DBUG_PRINT("info", ("default_part_db_type = %u", frm_image[61]));
|
||||
#endif
|
||||
legacy_db_type= (enum legacy_db_type) (uint) *(head+3);
|
||||
legacy_db_type= (enum legacy_db_type) (uint) *(frm_image+3);
|
||||
DBUG_ASSERT(share->db_plugin == NULL);
|
||||
/*
|
||||
if the storage engine is dynamic, no point in resolving it by its
|
||||
@ -841,23 +863,23 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
legacy_db_type < DB_TYPE_FIRST_DYNAMIC)
|
||||
share->db_plugin= ha_lock_engine(NULL,
|
||||
ha_checktype(thd, legacy_db_type, 0, 0));
|
||||
share->db_create_options= db_create_options= uint2korr(head+30);
|
||||
share->db_create_options= db_create_options= uint2korr(frm_image+30);
|
||||
share->db_options_in_use= share->db_create_options;
|
||||
share->mysql_version= uint4korr(head+51);
|
||||
share->mysql_version= uint4korr(frm_image+51);
|
||||
share->null_field_first= 0;
|
||||
if (!head[32]) // New frm file in 3.23
|
||||
if (!frm_image[32]) // New frm file in 3.23
|
||||
{
|
||||
share->avg_row_length= uint4korr(head+34);
|
||||
share->transactional= (ha_choice) (head[39] & 3);
|
||||
share->page_checksum= (ha_choice) ((head[39] >> 2) & 3);
|
||||
share->row_type= (row_type) head[40];
|
||||
share->table_charset= get_charset((((uint) head[41]) << 8) +
|
||||
(uint) head[38],MYF(0));
|
||||
share->avg_row_length= uint4korr(frm_image+34);
|
||||
share->transactional= (ha_choice) (frm_image[39] & 3);
|
||||
share->page_checksum= (ha_choice) ((frm_image[39] >> 2) & 3);
|
||||
share->row_type= (row_type) frm_image[40];
|
||||
share->table_charset= get_charset((((uint) frm_image[41]) << 8) +
|
||||
(uint) frm_image[38],MYF(0));
|
||||
share->null_field_first= 1;
|
||||
}
|
||||
if (!share->table_charset)
|
||||
{
|
||||
/* unknown charset in head[38] or pre-3.23 frm */
|
||||
/* unknown charset in frm_image[38] or pre-3.23 frm */
|
||||
if (use_mb(default_charset_info))
|
||||
{
|
||||
/* Warn that we may be changing the size of character columns */
|
||||
@ -872,14 +894,11 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
if (db_create_options & HA_OPTION_LONG_BLOB_PTR)
|
||||
share->blob_ptr_size= portable_sizeof_char_ptr;
|
||||
error=4;
|
||||
share->max_rows= uint4korr(head+18);
|
||||
share->min_rows= uint4korr(head+22);
|
||||
share->max_rows= uint4korr(frm_image+18);
|
||||
share->min_rows= uint4korr(frm_image+22);
|
||||
|
||||
/* Read keyinformation */
|
||||
key_info_length= (uint) uint2korr(head+28);
|
||||
mysql_file_seek(file, (ulong) uint2korr(head+6), MY_SEEK_SET, MYF(0));
|
||||
if (read_string(file,(uchar**) &disk_buff,key_info_length))
|
||||
goto err; /* purecov: inspected */
|
||||
disk_buff= frm_image + uint2korr(frm_image+6);
|
||||
if (disk_buff[0] & 0x80)
|
||||
{
|
||||
share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f);
|
||||
@ -1047,36 +1066,29 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
(keyinfo->comment.length > 0));
|
||||
}
|
||||
|
||||
share->reclength = uint2korr((head+16));
|
||||
share->reclength = uint2korr((frm_image+16));
|
||||
share->stored_rec_length= share->reclength;
|
||||
if (*(head+26) == 1)
|
||||
if (*(frm_image+26) == 1)
|
||||
share->system= 1; /* one-record-database */
|
||||
#ifdef HAVE_CRYPTED_FRM
|
||||
else if (*(head+26) == 2)
|
||||
else if (*(frm_image+26) == 2)
|
||||
{
|
||||
crypted= get_crypt_for_frm();
|
||||
share->crypted= 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
record_offset= (ulong) (uint2korr(head+6)+
|
||||
((uint2korr(head+14) == 0xffff ?
|
||||
uint4korr(head+47) : uint2korr(head+14))));
|
||||
record_offset= (ulong) (uint2korr(frm_image+6)+
|
||||
((uint2korr(frm_image+14) == 0xffff ?
|
||||
uint4korr(frm_image+47) : uint2korr(frm_image+14))));
|
||||
|
||||
if ((n_length= uint4korr(head+55)))
|
||||
if ((n_length= uint4korr(frm_image+55)))
|
||||
{
|
||||
/* Read extra data segment */
|
||||
uchar *next_chunk, *buff_end;
|
||||
DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
|
||||
if (!(extra_segment_buff= (uchar*) my_malloc(n_length + 1, MYF(MY_WME))))
|
||||
goto err;
|
||||
next_chunk= extra_segment_buff;
|
||||
if (mysql_file_pread(file, extra_segment_buff,
|
||||
n_length, record_offset + share->reclength,
|
||||
MYF(MY_NABP)))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
next_chunk= frm_image + record_offset + share->reclength;
|
||||
buff_end= next_chunk + n_length;
|
||||
share->connect_string.length= uint2korr(next_chunk);
|
||||
if (!(share->connect_string.str= strmake_root(&share->mem_root,
|
||||
(char*) next_chunk + 2,
|
||||
@ -1086,7 +1098,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
goto err;
|
||||
}
|
||||
next_chunk+= share->connect_string.length + 2;
|
||||
buff_end= extra_segment_buff + n_length;
|
||||
if (next_chunk + 2 < buff_end)
|
||||
{
|
||||
uint str_db_type_length= uint2korr(next_chunk);
|
||||
@ -1240,21 +1251,20 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
}
|
||||
DBUG_ASSERT(next_chunk <= buff_end);
|
||||
}
|
||||
share->key_block_size= uint2korr(head+62);
|
||||
share->key_block_size= uint2korr(frm_image+62);
|
||||
|
||||
error=4;
|
||||
extra_rec_buf_length= uint2korr(head+59);
|
||||
extra_rec_buf_length= uint2korr(frm_image+59);
|
||||
rec_buff_length= ALIGN_SIZE(share->reclength + 1 + extra_rec_buf_length);
|
||||
share->rec_buff_length= rec_buff_length;
|
||||
if (!(record= (uchar *) alloc_root(&share->mem_root,
|
||||
rec_buff_length)))
|
||||
goto err; /* purecov: inspected */
|
||||
share->default_values= record;
|
||||
if (mysql_file_pread(file, record, (size_t) share->reclength,
|
||||
record_offset, MYF(MY_NABP)))
|
||||
goto err; /* purecov: inspected */
|
||||
memcpy(record, frm_image + record_offset, share->reclength);
|
||||
|
||||
disk_buff= frm_image + pos + 288;
|
||||
|
||||
mysql_file_seek(file, pos+288, MY_SEEK_SET, MYF(0));
|
||||
#ifdef HAVE_CRYPTED_FRM
|
||||
if (crypted)
|
||||
{
|
||||
@ -1300,8 +1310,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
read_length=(uint) (share->fields * field_pack_length +
|
||||
pos+ (uint) (n_length+int_length+com_length+
|
||||
vcol_screen_length));
|
||||
if (read_string(file,(uchar**) &disk_buff,read_length))
|
||||
goto err; /* purecov: inspected */
|
||||
#ifdef HAVE_CRYPTED_FRM
|
||||
if (crypted)
|
||||
{
|
||||
@ -1923,8 +1931,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
}
|
||||
else
|
||||
share->primary_key= MAX_KEY;
|
||||
my_free(disk_buff);
|
||||
disk_buff=0;
|
||||
if (new_field_pack_flag <= 1)
|
||||
{
|
||||
/* Old file format with default as not null */
|
||||
@ -2000,15 +2006,12 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
|
||||
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);
|
||||
@ -2820,50 +2823,6 @@ void free_field_buffers_larger_than(TABLE *table, uint32 size)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Find where a form starts.
|
||||
|
||||
@param head The start of the form file.
|
||||
|
||||
@remark If formname is NULL then only formnames is read.
|
||||
|
||||
@retval The form position.
|
||||
*/
|
||||
|
||||
static ulong get_form_pos(File file, uchar *head)
|
||||
{
|
||||
uchar *pos, *buf;
|
||||
uint names, length;
|
||||
ulong ret_value=0;
|
||||
DBUG_ENTER("get_form_pos");
|
||||
|
||||
names= uint2korr(head+8);
|
||||
|
||||
if (!(names= uint2korr(head+8)))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
length= uint2korr(head+4);
|
||||
|
||||
mysql_file_seek(file, 64L, MY_SEEK_SET, MYF(0));
|
||||
|
||||
if (!(buf= (uchar*) my_malloc(length+names*4, MYF(MY_WME))))
|
||||
DBUG_RETURN(0);
|
||||
|
||||
if (mysql_file_read(file, buf, length+names*4, MYF(MY_NABP)))
|
||||
{
|
||||
my_free(buf);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
pos= buf+length;
|
||||
ret_value= uint4korr(pos);
|
||||
|
||||
my_free(buf);
|
||||
|
||||
DBUG_RETURN(ret_value);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Read string from a file with malloc
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user