Skip to content

Commit

Permalink
MDEV-11084 Select statement with partition selection against MyISAM t…
Browse files Browse the repository at this point in the history
…able 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.
  • Loading branch information
Alexey Botchkov committed Jan 29, 2018
1 parent 041a32a commit b4a2baf
Show file tree
Hide file tree
Showing 16 changed files with 252 additions and 61 deletions.
Binary file added mysql-test/std_data/mdev11084.frm
Binary file not shown.
Binary file added mysql-test/std_data/mdev11084.par
Binary file not shown.
Binary file added mysql-test/std_data/mdev11084.part1.MYD
Binary file not shown.
Binary file added mysql-test/std_data/mdev11084.part1.MYI
Binary file not shown.
8 changes: 8 additions & 0 deletions mysql-test/suite/parts/r/partition_open.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
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")
24 changes: 24 additions & 0 deletions mysql-test/suite/parts/t/partition_open.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#
# 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;
184 changes: 146 additions & 38 deletions sql/ha_partition.cc
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ void ha_partition::init_handler_variables()
part_share= NULL;
m_new_partitions_share_refs.empty();
m_part_ids_sorted_by_num_of_records= NULL;
m_partitions_to_open= NULL;

m_range_info= NULL;
m_mrr_full_buffer_size= 0;
Expand All @@ -389,6 +390,7 @@ void ha_partition::init_handler_variables()
my_bitmap_clear(&m_partitions_to_reset);
my_bitmap_clear(&m_key_not_found_partitions);
my_bitmap_clear(&m_mrr_used_partitions);
my_bitmap_clear(&m_opened_partitions);

#ifdef DONT_HAVE_TO_BE_INITALIZED
m_start_key.flag= 0;
Expand Down Expand Up @@ -3360,6 +3362,7 @@ void ha_partition::free_partition_bitmaps()
my_bitmap_free(&m_locked_partitions);
my_bitmap_free(&m_partitions_to_reset);
my_bitmap_free(&m_key_not_found_partitions);
my_bitmap_free(&m_opened_partitions);
my_bitmap_free(&m_mrr_used_partitions);
}

Expand Down Expand Up @@ -3401,6 +3404,9 @@ bool ha_partition::init_partition_bitmaps()
if (bitmap_init(&m_mrr_used_partitions, NULL, m_tot_parts, TRUE))
DBUG_RETURN(true);

if (my_bitmap_init(&m_opened_partitions, NULL, m_tot_parts, FALSE))
DBUG_RETURN(true);

/* Initialize the bitmap for read/lock_partitions */
if (!m_is_clone_of)
{
Expand Down Expand Up @@ -3437,8 +3443,8 @@ bool ha_partition::init_partition_bitmaps()

int ha_partition::open(const char *name, int mode, uint test_if_locked)
{
char *name_buffer_ptr;
int error= HA_ERR_INITIALIZATION;
handler *file_sample= NULL;
handler **file;
char name_buff[FN_REFLEN + 1];
ulonglong check_table_flags;
Expand All @@ -3451,7 +3457,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
m_part_field_array= m_part_info->full_part_field_array;
if (get_from_handler_file(name, &table->mem_root, MY_TEST(m_is_clone_of)))
DBUG_RETURN(error);
name_buffer_ptr= m_name_buffer_ptr;
if (populate_partition_name_hash())
{
DBUG_RETURN(HA_ERR_INITIALIZATION);
Expand All @@ -3473,6 +3478,9 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
if (init_partition_bitmaps())
goto err_alloc;

if ((error= m_part_info->set_partition_bitmaps(m_partitions_to_open)))
goto err_alloc;

/* Allocate memory used with MMR */
if (!(m_range_info= (void **)
my_multi_malloc(MYF(MY_WME),
Expand All @@ -3498,6 +3506,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
if (m_is_clone_of)
{
uint i, alloc_len;
char *name_buffer_ptr;
DBUG_ASSERT(m_clone_mem_root);
/* Allocate an array of handler pointers for the partitions handlers. */
alloc_len= (m_tot_parts + 1) * sizeof(handler*);
Expand All @@ -3507,13 +3516,17 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
goto err_alloc;
}
memset(m_file, 0, alloc_len);
name_buffer_ptr= m_name_buffer_ptr;
/*
Populate them by cloning the original partitions. This also opens them.
Note that file->ref is allocated too.
*/
file= m_is_clone_of->m_file;
for (i= 0; i < m_tot_parts; i++)
{
if (!bitmap_is_set(&m_is_clone_of->m_opened_partitions, i))
continue;

if ((error= create_partition_name(name_buff, sizeof(name_buff), name,
name_buffer_ptr, NORMAL_PART_NAME, FALSE)))
goto err_handler;
Expand All @@ -3524,30 +3537,18 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
file= &m_file[i];
goto err_handler;
}
if (!file_sample)
file_sample= m_file[i];
name_buffer_ptr+= strlen(name_buffer_ptr) + 1;
bitmap_set_bit(&m_opened_partitions, i);
}
}
else
{
file= m_file;
do
{
LEX_CSTRING save_connect_string= table->s->connect_string;
if ((error= create_partition_name(name_buff, sizeof(name_buff), name,
name_buffer_ptr, NORMAL_PART_NAME, FALSE)))
goto err_handler;
if (!((*file)->ht->flags & HTON_CAN_READ_CONNECT_STRING_IN_PARTITION))
table->s->connect_string= m_connect_string[(uint)(file-m_file)];
error= (*file)->ha_open(table, name_buff, mode,
test_if_locked | HA_OPEN_NO_PSI_CALL);
table->s->connect_string= save_connect_string;
if (error)
goto err_handler;
if (m_file == file)
m_num_locks= (*file)->lock_count();
DBUG_ASSERT(m_num_locks == (*file)->lock_count());
name_buffer_ptr+= strlen(name_buffer_ptr) + 1;
} while (*(++file));
if ((error= open_read_partitions(name_buff, sizeof(name_buff),
&file_sample)))
goto err_handler;
m_num_locks= file_sample->lock_count();
}
/*
We want to know the upper bound for locks, to allocate enough memory.
Expand All @@ -3558,12 +3559,14 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
m_num_locks*= m_tot_parts;

file= m_file;
ref_length= (*file)->ref_length;
check_table_flags= (((*file)->ha_table_flags() &
ref_length= file_sample->ref_length;
check_table_flags= ((file_sample->ha_table_flags() &
~(PARTITION_DISABLED_TABLE_FLAGS)) |
(PARTITION_ENABLED_TABLE_FLAGS));
while (*(++file))
{
if (!bitmap_is_set(&m_opened_partitions, file - m_file))
continue;
/* MyISAM can have smaller ref_length for partitions with MAX_ROWS set */
set_if_bigger(ref_length, ((*file)->ref_length));
/*
Expand All @@ -3580,8 +3583,8 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
goto err_handler;
}
}
key_used_on_scan= m_file[0]->key_used_on_scan;
implicit_emptied= m_file[0]->implicit_emptied;
key_used_on_scan= file_sample->key_used_on_scan;
implicit_emptied= file_sample->implicit_emptied;
/*
Add 2 bytes for partition id in position ref length.
ref_length=max_in_all_partitions(ref_length) + PARTITION_BYTES_IN_POS
Expand Down Expand Up @@ -3612,8 +3615,12 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)

err_handler:
DEBUG_SYNC(ha_thd(), "partition_open_error");
file= &m_file[m_tot_parts - 1];
while (file-- != m_file)
(*file)->ha_close();
{
if (bitmap_is_set(&m_opened_partitions, file - m_file))
(*file)->ha_close();
}
err_alloc:
free_partition_bitmaps();
my_free(m_range_info);
Expand Down Expand Up @@ -3744,7 +3751,6 @@ int ha_partition::close(void)
DBUG_ASSERT(m_part_info);

destroy_record_priority_queue();
free_partition_bitmaps();

for (; ft_first ; ft_first= tmp_ft_info)
{
Expand Down Expand Up @@ -3795,9 +3801,12 @@ int ha_partition::close(void)
repeat:
do
{
(*file)->ha_close();
if (!first || bitmap_is_set(&m_opened_partitions, file - m_file))
(*file)->ha_close();
} while (*(++file));

free_partition_bitmaps();

if (first && m_added_file && m_added_file[0])
{
file= m_added_file;
Expand Down Expand Up @@ -8246,15 +8255,18 @@ int ha_partition::info(uint flag)
do
{
file= *file_array;
/* Get variables if not already done */
if (!(flag & HA_STATUS_VARIABLE) ||
!bitmap_is_set(&(m_part_info->read_partitions),
(uint)(file_array - m_file)))
file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag);
if (file->stats.records > max_records)
if (bitmap_is_set(&(m_opened_partitions), (file_array - m_file)))
{
max_records= file->stats.records;
handler_instance= i;
/* Get variables if not already done */
if (!(flag & HA_STATUS_VARIABLE) ||
!bitmap_is_set(&(m_part_info->read_partitions),
(uint) (file_array - m_file)))
file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag);
if (file->stats.records > max_records)
{
max_records= file->stats.records;
handler_instance= i;
}
}
i++;
} while (*(++file_array));
Expand Down Expand Up @@ -8335,6 +8347,96 @@ void ha_partition::get_dynamic_partition_info(PARTITION_STATS *stat_info,
}


void ha_partition::set_partitions_to_open(List<String> *partition_names)
{
m_partitions_to_open= partition_names;
}


int ha_partition::open_read_partitions(char *name_buff, size_t name_buff_size,
handler **sample)
{
handler **file;
char *name_buffer_ptr;
int error;

name_buffer_ptr= m_name_buffer_ptr;
file= m_file;
*sample= NULL;
do
{
int n_file= file-m_file;
int is_open= bitmap_is_set(&m_opened_partitions, n_file);
int should_be_open= bitmap_is_set(&m_part_info->read_partitions, n_file);

if (is_open && !should_be_open)
{
if ((error= (*file)->ha_close()))
goto err_handler;
bitmap_clear_bit(&m_opened_partitions, n_file);
}
else if (!is_open && should_be_open)
{
LEX_CSTRING save_connect_string= table->s->connect_string;
if ((error= create_partition_name(name_buff, name_buff_size,
table->s->normalized_path.str,
name_buffer_ptr, NORMAL_PART_NAME, FALSE)))
goto err_handler;
if (!((*file)->ht->flags & HTON_CAN_READ_CONNECT_STRING_IN_PARTITION))
table->s->connect_string= m_connect_string[(uint)(file-m_file)];
error= (*file)->ha_open(table, name_buff, m_mode,
m_open_test_lock | HA_OPEN_NO_PSI_CALL);
table->s->connect_string= save_connect_string;
if (error)
goto err_handler;
if (!(*sample))
*sample= *file;
bitmap_set_bit(&m_opened_partitions, n_file);
}
name_buffer_ptr+= strlen(name_buffer_ptr) + 1;
} while (*(++file));

err_handler:
return error;
}


int ha_partition::change_partitions_to_open(List<String> *partition_names)
{
char name_buff[FN_REFLEN+1];
int error= 0;
handler *sample;

if (m_is_clone_of)
return 0;

m_partitions_to_open= partition_names;
if ((error= m_part_info->set_partition_bitmaps(partition_names)))
goto err_handler;

if (m_lock_type != F_UNLCK)
{
/*
That happens after the LOCK TABLE statement.
Do nothing in this case.
*/
return 0;
}

if (bitmap_cmp(&m_opened_partitions, &m_part_info->read_partitions) != 0)
return 0;

if ((error= read_par_file(table->s->normalized_path.str)) ||
(error= open_read_partitions(name_buff, sizeof(name_buff), &sample)))
goto err_handler;

clear_handler_file();

err_handler:
return error;
}


/**
General function to prepare handler for certain behavior.
Expand Down Expand Up @@ -8831,7 +8933,8 @@ int ha_partition::reset(void)
i < m_tot_parts;
i= bitmap_get_next_set(&m_partitions_to_reset, i))
{
if ((tmp= m_file[i]->ha_reset()))
if (bitmap_is_set(&m_opened_partitions, i) &&
(tmp= m_file[i]->ha_reset()))
result= tmp;
}
bitmap_clear_all(&m_partitions_to_reset);
Expand Down Expand Up @@ -8948,7 +9051,12 @@ int ha_partition::loop_extra(enum ha_extra_function operation)
i < m_tot_parts;
i= bitmap_get_next_set(&m_part_info->lock_partitions, i))
{
if ((tmp= m_file[i]->extra(operation)))
/*
This can be called after an error in ha_open.
In this case calling 'extra' can crash.
*/
if (bitmap_is_set(&m_opened_partitions, i) &&
(tmp= m_file[i]->extra(operation)))
result= tmp;
}
/* Add all used partitions to be called in reset(). */
Expand Down
6 changes: 6 additions & 0 deletions sql/ha_partition.h
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit b4a2baf

Please sign in to comment.