Commit 0973b7a8 authored by Sergei Golubchik's avatar Sergei Golubchik

partitioning frm bugs:

1. default db type for partitions was stored as 1-byte DB_TYPE code,
   which doesn't work for dynamically generated codes.
2. storage engine plugin for default db type wasn't locked at all,
   which could trivially crash for dynamic plugins.

Now the storage engine name is stored in the extra2 section,
and the plugin is correctly locked.
parent 54b3472e
......@@ -4914,7 +4914,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
if (share->db_type() == partition_hton &&
share->partition_info_str_len)
{
tmp_db_type= share->default_part_db_type;
tmp_db_type= plugin_hton(share->default_part_plugin);
is_partitioned= TRUE;
}
#endif
......
......@@ -454,6 +454,7 @@ void TABLE_SHARE::destroy()
ha_data_destroy= NULL;
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
plugin_unlock(NULL, default_part_plugin);
if (ha_part_data_destroy)
{
ha_part_data_destroy(ha_part_data);
......@@ -798,6 +799,16 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
options= extra2;
options_len= length;
break;
case EXTRA2_DEFAULT_PART_ENGINE:
#ifdef WITH_PARTITION_STORAGE_ENGINE
{
LEX_STRING name= { (char*)extra2, length };
share->default_part_plugin= ha_resolve_by_name(NULL, &name);
if (!share->default_part_plugin)
goto err;
}
#endif
break;
default:
/* abort frm parsing if it's an unknown but important extra2 value */
if (type >= EXTRA2_ENGINE_IMPORTANT)
......@@ -828,11 +839,14 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
share->frm_version= FRM_VER_TRUE_VARCHAR;
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (frm_image[61] &&
!(share->default_part_db_type=
ha_checktype(thd, (enum legacy_db_type) (uint) frm_image[61], 1, 0)))
if (frm_image[61] && !share->default_part_plugin)
{
enum legacy_db_type db_type= (enum legacy_db_type) (uint) frm_image[61];
share->default_part_plugin=
ha_lock_engine(NULL, ha_checktype(thd, db_type, 1, 0));
if (!share->default_part_plugin)
goto err;
DBUG_PRINT("info", ("default_part_db_type = %u", frm_image[61]));
}
#endif
legacy_db_type= (enum legacy_db_type) (uint) frm_image[3];
/*
......@@ -2697,7 +2711,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
tmp= mysql_unpack_partition(thd, share->partition_info_str,
share->partition_info_str_len,
outparam, is_create_table,
share->default_part_db_type,
plugin_hton(share->default_part_plugin),
&work_part_info_used);
if (tmp)
{
......
......@@ -741,7 +741,7 @@ struct TABLE_SHARE
char *partition_info_str;
uint partition_info_str_len;
uint partition_info_buffer_size;
handlerton *default_part_db_type;
plugin_ref default_part_plugin;
#endif
/**
......
......@@ -46,6 +46,38 @@ static bool pack_fields(uchar *, List<Create_field> &, ulong);
static size_t packed_fields_length(List<Create_field> &);
static bool make_empty_rec(THD *, uchar *, uint, List<Create_field> &, uint, ulong);
static uchar *extra2_write_len(uchar *pos, size_t len)
{
if (len < 255)
*pos++= len;
else
{
/*
At the moment we support options_len up to 64K.
We can easily extend it in the future, if the need arises.
*/
DBUG_ASSERT(len <= 65535);
int2store(pos + 1, len);
pos+= 3;
}
return pos;
}
static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
LEX_STRING *str)
{
*pos++ = type;
pos= extra2_write_len(pos, str->length);
memcpy(pos, str->str, str->length);
return pos + str->length;
}
static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type,
LEX_CUSTRING *str)
{
return extra2_write(pos, type, reinterpret_cast<LEX_STRING *>(str));
}
/**
Create a frm (table definition) file
......@@ -200,6 +232,9 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
if (options_len)
extra2_size+= 1 + (options_len > 255 ? 3 : 1) + options_len;
if (part_info)
extra2_size+= 1 + 1 + hton_name(part_info->default_engine_type)->length;
key_buff_length= uint4korr(fileinfo+47);
frm.length= FRM_HEADER_SIZE; // fileinfo;
......@@ -223,27 +258,17 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table,
/* write the extra2 segment */
pos = frm_ptr + 64;
compile_time_assert(EXTRA2_TABLEDEF_VERSION != '/');
*pos++ = EXTRA2_TABLEDEF_VERSION; // old servers write '/' here
*pos++ = create_info->tabledef_version.length;
memcpy(pos, create_info->tabledef_version.str,
create_info->tabledef_version.length);
pos+= create_info->tabledef_version.length;
pos= extra2_write(pos, EXTRA2_TABLEDEF_VERSION,
&create_info->tabledef_version);
if (part_info)
pos= extra2_write(pos, EXTRA2_DEFAULT_PART_ENGINE,
hton_name(part_info->default_engine_type));
if (options_len)
{
*pos++= EXTRA2_ENGINE_TABLEOPTS;
if (options_len < 255)
*pos++= options_len;
else
{
/*
At the moment we support options_len up to 64K.
We can easily extend it in the future, if the need arises.
*/
DBUG_ASSERT(options_len <= 65535);
int2store(pos + 1, options_len);
pos+= 3;
}
pos= extra2_write_len(pos, options_len);
pos= engine_table_options_frm_image(pos, create_info->option_list,
create_fields, keys, key_info);
}
......
......@@ -181,6 +181,7 @@
*/
enum extra2_frm_value_type {
EXTRA2_TABLEDEF_VERSION=0,
EXTRA2_DEFAULT_PART_ENGINE=1,
#define EXTRA2_ENGINE_IMPORTANT 128
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment