Commit b4a2baff authored by Alexey Botchkov's avatar Alexey Botchkov

MDEV-11084 Select statement with partition selection against MyISAM table opens all partitions.

        Now we don't open partitions if it was explicitly cpecified.
        ha_partition::m_opened_partition bitmap added to track
        partitions that were actually opened.
parent 041a32ab
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
select * from t1 partition (p1);
x
300
select * from t1 partition (p0);
ERROR HY000: Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory")
drop table t1;
Warnings:
Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory")
#
# MDEV-11084 Select statement with partition selection against MyISAM table opens all partitions.
#
--source include/have_partition.inc
let $datadir=`select @@datadir`;
# Table declared as having 2 partitions
# create table t1 (x int) egine=myisam
# partition by range columns (x)
# ( partition p0 values less than (100), partition p1 values less than (1000));
#
# But we copy only second partition. So the 'p0' can't be opened.
copy_file std_data/mdev11084.frm $datadir/test/t1.frm;
copy_file std_data/mdev11084.par $datadir/test/t1.par;
copy_file std_data/mdev11084.part1.MYD $datadir/test/t1#P#p1.MYD;
copy_file std_data/mdev11084.part1.MYI $datadir/test/t1#P#p1.MYI;
select * from t1 partition (p1);
--replace_result $datadir ./
--error ER_FILE_NOT_FOUND
select * from t1 partition (p0);
--replace_result $datadir ./
drop table t1;
This diff is collapsed.
......@@ -385,6 +385,8 @@ class ha_partition :public handler
/** partitions that returned HA_ERR_KEY_NOT_FOUND. */
MY_BITMAP m_key_not_found_partitions;
bool m_key_not_found;
List<String> *m_partitions_to_open;
MY_BITMAP m_opened_partitions;
public:
handler **get_child_handlers()
{
......@@ -836,6 +838,10 @@ class ha_partition :public handler
virtual int info(uint);
void get_dynamic_partition_info(PARTITION_STATS *stat_info,
uint part_id);
void set_partitions_to_open(List<String> *partition_names);
int change_partitions_to_open(List<String> *partition_names);
int open_read_partitions(char *name_buff, size_t name_buff_size,
handler **sample);
virtual int extra(enum ha_extra_function operation);
virtual int extra_opt(enum ha_extra_function operation, ulong cachesize);
virtual int reset(void);
......
......@@ -2661,7 +2661,8 @@ PSI_table_share *handler::ha_table_share_psi() const
Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set
*/
int handler::ha_open(TABLE *table_arg, const char *name, int mode,
uint test_if_locked, MEM_ROOT *mem_root)
uint test_if_locked, MEM_ROOT *mem_root,
List<String> *partitions_to_open)
{
int error;
DBUG_ENTER("handler::ha_open");
......@@ -2676,6 +2677,8 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
DBUG_PRINT("info", ("old m_lock_type: %d F_UNLCK %d", m_lock_type, F_UNLCK));
DBUG_ASSERT(alloc_root_inited(&table->mem_root));
set_partitions_to_open(partitions_to_open);
if ((error=open(name,mode,test_if_locked)))
{
if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
......
......@@ -2990,7 +2990,7 @@ class handler :public Sql_alloc
/* ha_ methods: pubilc wrappers for private virtual API */
int ha_open(TABLE *table, const char *name, int mode, uint test_if_locked,
MEM_ROOT *mem_root= 0);
MEM_ROOT *mem_root= 0, List<String> *partitions_to_open=NULL);
int ha_index_init(uint idx, bool sorted)
{
DBUG_EXECUTE_IF("ha_index_init_fail", return HA_ERR_TABLE_DEF_CHANGED;);
......@@ -3569,6 +3569,9 @@ class handler :public Sql_alloc
virtual int info(uint)=0; // see my_base.h for full description
virtual void get_dynamic_partition_info(PARTITION_STATS *stat_info,
uint part_id);
virtual void set_partitions_to_open(List<String> *partition_names) {}
virtual int change_partitions_to_open(List<String> *partition_names)
{ return 0; }
virtual int extra(enum ha_extra_function operation)
{ return 0; }
virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
......
......@@ -256,16 +256,16 @@ bool partition_info::set_read_partitions(List<char> *partition_names)
Prune away partitions not mentioned in the PARTITION () clause,
if used.
@param table_list Table list pointing to table to prune.
@param partition_names list of names of partitions.
@return Operation status
@retval true Failure
@retval false Success
*/
bool partition_info::prune_partition_bitmaps(TABLE_LIST *table_list)
bool partition_info::prune_partition_bitmaps(List<String> *partition_names)
{
List_iterator<String> partition_names_it(*(table_list->partition_names));
uint num_names= table_list->partition_names->elements;
List_iterator<String> partition_names_it(*(partition_names));
uint num_names= partition_names->elements;
uint i= 0;
DBUG_ENTER("partition_info::prune_partition_bitmaps");
......@@ -295,8 +295,7 @@ bool partition_info::prune_partition_bitmaps(TABLE_LIST *table_list)
/**
Set read/lock_partitions bitmap over non pruned partitions
@param table_list Possible TABLE_LIST which can contain
list of partition names to query
@param partition_names list of partition names to query
@return Operation status
@retval FALSE OK
......@@ -306,7 +305,7 @@ bool partition_info::prune_partition_bitmaps(TABLE_LIST *table_list)
@note OK to call multiple times without the need for free_bitmaps.
*/
bool partition_info::set_partition_bitmaps(TABLE_LIST *table_list)
bool partition_info::set_partition_bitmaps(List<String> *partition_names)
{
DBUG_ENTER("partition_info::set_partition_bitmaps");
......@@ -315,16 +314,15 @@ bool partition_info::set_partition_bitmaps(TABLE_LIST *table_list)
if (!bitmaps_are_initialized)
DBUG_RETURN(TRUE);
if (table_list &&
table_list->partition_names &&
table_list->partition_names->elements)
if (partition_names &&
partition_names->elements)
{
if (table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)
{
my_error(ER_PARTITION_CLAUSE_ON_NONPARTITIONED, MYF(0));
DBUG_RETURN(true);
}
if (prune_partition_bitmaps(table_list))
if (prune_partition_bitmaps(partition_names))
DBUG_RETURN(TRUE);
}
else
......@@ -338,6 +336,27 @@ bool partition_info::set_partition_bitmaps(TABLE_LIST *table_list)
}
/**
Set read/lock_partitions bitmap over non pruned partitions
@param table_list Possible TABLE_LIST which can contain
list of partition names to query
@return Operation status
@retval FALSE OK
@retval TRUE Failed to allocate memory for bitmap or list of partitions
did not match
@note OK to call multiple times without the need for free_bitmaps.
*/
bool partition_info::set_partition_bitmaps_from_table(TABLE_LIST *table_list)
{
List<String> *partition_names= table_list ?
NULL : table_list->partition_names;
return set_partition_bitmaps(partition_names);
}
/*
Create a memory area where default partition names are stored and fill it
up with the names.
......
......@@ -325,7 +325,8 @@ class partition_info : public Sql_alloc
partition_info *get_clone(THD *thd);
bool set_named_partition_bitmap(const char *part_name, uint length);
bool set_partition_bitmaps(TABLE_LIST *table_list);
bool set_partition_bitmaps(List<String> *partition_names);
bool set_partition_bitmaps_from_table(TABLE_LIST *table_list);
/* Answers the question if subpartitioning is used for a certain table */
bool is_sub_partitioned()
{
......@@ -386,7 +387,7 @@ class partition_info : public Sql_alloc
char *create_default_subpartition_name(THD *thd, uint subpart_no,
const char *part_name);
// FIXME: prune_partition_bitmaps() is duplicate of set_read_partitions()
bool prune_partition_bitmaps(TABLE_LIST *table_list);
bool prune_partition_bitmaps(List<String> *partition_names);
bool add_named_partition(const char *part_name, uint length);
public:
bool set_read_partitions(List<char> *partition_names);
......
......@@ -1512,6 +1512,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
MDL_ticket *mdl_ticket;
TABLE_SHARE *share;
uint gts_flags;
int part_names_error=0;
DBUG_ENTER("open_table");
/*
......@@ -1609,6 +1610,12 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
table= best_table;
table->query_id= thd->query_id;
DBUG_PRINT("info",("Using locked table"));
if (table->part_info)
{
/* Set all [named] partitions as used. */
part_names_error=
table->file->change_partitions_to_open(table_list->partition_names);
}
goto reset;
}
/*
......@@ -1892,6 +1899,12 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
{
DBUG_ASSERT(table->file != NULL);
MYSQL_REBIND_TABLE(table->file);
if (table->part_info)
{
/* Set all [named] partitions as used. */
part_names_error=
table->file->change_partitions_to_open(table_list->partition_names);
}
}
else
{
......@@ -1904,7 +1917,8 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
error= open_table_from_share(thd, share, alias,
HA_OPEN_KEYFILE | HA_TRY_READ_ONLY,
EXTRA_RECORD,
thd->open_options, table, FALSE);
thd->open_options, table, FALSE,
table_list->partition_names);
if (error)
{
......@@ -1953,9 +1967,12 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (table->part_info)
{
/* Set all [named] partitions as used. */
if (table->part_info->set_partition_bitmaps(table_list))
/* Partitions specified were incorrect.*/
if (part_names_error)
{
table->file->print_error(part_names_error, MYF(0));
DBUG_RETURN(true);
}
}
else if (table_list->partition_names)
{
......
......@@ -802,8 +802,8 @@ bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd)
DBUG_RETURN(true);
partition_names_list.push_back(str_partition_name, thd->mem_root);
}
first_table->partition_names= &partition_names_list;
if (first_table->table->part_info->set_partition_bitmaps(first_table))
if (first_table->table->
part_info->set_partition_bitmaps(&partition_names_list))
DBUG_RETURN(true);
if (lock_tables(thd, first_table, table_counter, 0))
......
......@@ -3100,6 +3100,7 @@ static bool check_vcol_forward_refs(Field *field, Virtual_column_info *vcol)
prgflag READ_ALL etc..
ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc..
outparam result table
partitions_to_open open only these partitions.
RETURN VALUES
0 ok
......@@ -3114,7 +3115,7 @@ static bool check_vcol_forward_refs(Field *field, Virtual_column_info *vcol)
enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
const char *alias, uint db_stat, uint prgflag,
uint ha_open_flags, TABLE *outparam,
bool is_create_table)
bool is_create_table, List<String> *partitions_to_open)
{
enum open_frm_error error;
uint records, i, bitmap_size, bitmap_count;
......@@ -3458,7 +3459,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
int ha_err= outparam->file->ha_open(outparam, share->normalized_path.str,
(db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR),
ha_open_flags);
ha_open_flags, 0, partitions_to_open);
if (ha_err)
{
share->open_errno= ha_err;
......
......@@ -2885,7 +2885,8 @@ void init_mdl_requests(TABLE_LIST *table_list);
enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
const char *alias, uint db_stat, uint prgflag,
uint ha_open_flags, TABLE *outparam,
bool is_create_table);
bool is_create_table,
List<String> *partitions_to_open= NULL);
bool fix_session_vcol_expr(THD *thd, Virtual_column_info *vcol);
bool fix_session_vcol_expr_for_read(THD *thd, Field *field,
Virtual_column_info *vcol);
......
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