Skip to content

Commit b4a2baf

Browse files
author
Alexey Botchkov
committed
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.
1 parent 041a32a commit b4a2baf

16 files changed

+252
-61
lines changed

mysql-test/std_data/mdev11084.frm

589 Bytes
Binary file not shown.

mysql-test/std_data/mdev11084.par

36 Bytes
Binary file not shown.
7 Bytes
Binary file not shown.
1 KB
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
select * from t1 partition (p1);
2+
x
3+
300
4+
select * from t1 partition (p0);
5+
ERROR HY000: Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory")
6+
drop table t1;
7+
Warnings:
8+
Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory")
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#
2+
# MDEV-11084 Select statement with partition selection against MyISAM table opens all partitions.
3+
#
4+
--source include/have_partition.inc
5+
6+
let $datadir=`select @@datadir`;
7+
8+
# Table declared as having 2 partitions
9+
# create table t1 (x int) egine=myisam
10+
# partition by range columns (x)
11+
# ( partition p0 values less than (100), partition p1 values less than (1000));
12+
#
13+
# But we copy only second partition. So the 'p0' can't be opened.
14+
15+
copy_file std_data/mdev11084.frm $datadir/test/t1.frm;
16+
copy_file std_data/mdev11084.par $datadir/test/t1.par;
17+
copy_file std_data/mdev11084.part1.MYD $datadir/test/t1#P#p1.MYD;
18+
copy_file std_data/mdev11084.part1.MYI $datadir/test/t1#P#p1.MYI;
19+
select * from t1 partition (p1);
20+
--replace_result $datadir ./
21+
--error ER_FILE_NOT_FOUND
22+
select * from t1 partition (p0);
23+
--replace_result $datadir ./
24+
drop table t1;

sql/ha_partition.cc

Lines changed: 146 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ void ha_partition::init_handler_variables()
368368
part_share= NULL;
369369
m_new_partitions_share_refs.empty();
370370
m_part_ids_sorted_by_num_of_records= NULL;
371+
m_partitions_to_open= NULL;
371372

372373
m_range_info= NULL;
373374
m_mrr_full_buffer_size= 0;
@@ -389,6 +390,7 @@ void ha_partition::init_handler_variables()
389390
my_bitmap_clear(&m_partitions_to_reset);
390391
my_bitmap_clear(&m_key_not_found_partitions);
391392
my_bitmap_clear(&m_mrr_used_partitions);
393+
my_bitmap_clear(&m_opened_partitions);
392394

393395
#ifdef DONT_HAVE_TO_BE_INITALIZED
394396
m_start_key.flag= 0;
@@ -3360,6 +3362,7 @@ void ha_partition::free_partition_bitmaps()
33603362
my_bitmap_free(&m_locked_partitions);
33613363
my_bitmap_free(&m_partitions_to_reset);
33623364
my_bitmap_free(&m_key_not_found_partitions);
3365+
my_bitmap_free(&m_opened_partitions);
33633366
my_bitmap_free(&m_mrr_used_partitions);
33643367
}
33653368

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

3407+
if (my_bitmap_init(&m_opened_partitions, NULL, m_tot_parts, FALSE))
3408+
DBUG_RETURN(true);
3409+
34043410
/* Initialize the bitmap for read/lock_partitions */
34053411
if (!m_is_clone_of)
34063412
{
@@ -3437,8 +3443,8 @@ bool ha_partition::init_partition_bitmaps()
34373443

34383444
int ha_partition::open(const char *name, int mode, uint test_if_locked)
34393445
{
3440-
char *name_buffer_ptr;
34413446
int error= HA_ERR_INITIALIZATION;
3447+
handler *file_sample= NULL;
34423448
handler **file;
34433449
char name_buff[FN_REFLEN + 1];
34443450
ulonglong check_table_flags;
@@ -3451,7 +3457,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
34513457
m_part_field_array= m_part_info->full_part_field_array;
34523458
if (get_from_handler_file(name, &table->mem_root, MY_TEST(m_is_clone_of)))
34533459
DBUG_RETURN(error);
3454-
name_buffer_ptr= m_name_buffer_ptr;
34553460
if (populate_partition_name_hash())
34563461
{
34573462
DBUG_RETURN(HA_ERR_INITIALIZATION);
@@ -3473,6 +3478,9 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
34733478
if (init_partition_bitmaps())
34743479
goto err_alloc;
34753480

3481+
if ((error= m_part_info->set_partition_bitmaps(m_partitions_to_open)))
3482+
goto err_alloc;
3483+
34763484
/* Allocate memory used with MMR */
34773485
if (!(m_range_info= (void **)
34783486
my_multi_malloc(MYF(MY_WME),
@@ -3498,6 +3506,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
34983506
if (m_is_clone_of)
34993507
{
35003508
uint i, alloc_len;
3509+
char *name_buffer_ptr;
35013510
DBUG_ASSERT(m_clone_mem_root);
35023511
/* Allocate an array of handler pointers for the partitions handlers. */
35033512
alloc_len= (m_tot_parts + 1) * sizeof(handler*);
@@ -3507,13 +3516,17 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
35073516
goto err_alloc;
35083517
}
35093518
memset(m_file, 0, alloc_len);
3519+
name_buffer_ptr= m_name_buffer_ptr;
35103520
/*
35113521
Populate them by cloning the original partitions. This also opens them.
35123522
Note that file->ref is allocated too.
35133523
*/
35143524
file= m_is_clone_of->m_file;
35153525
for (i= 0; i < m_tot_parts; i++)
35163526
{
3527+
if (!bitmap_is_set(&m_is_clone_of->m_opened_partitions, i))
3528+
continue;
3529+
35173530
if ((error= create_partition_name(name_buff, sizeof(name_buff), name,
35183531
name_buffer_ptr, NORMAL_PART_NAME, FALSE)))
35193532
goto err_handler;
@@ -3524,30 +3537,18 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
35243537
file= &m_file[i];
35253538
goto err_handler;
35263539
}
3540+
if (!file_sample)
3541+
file_sample= m_file[i];
35273542
name_buffer_ptr+= strlen(name_buffer_ptr) + 1;
3543+
bitmap_set_bit(&m_opened_partitions, i);
35283544
}
35293545
}
35303546
else
35313547
{
3532-
file= m_file;
3533-
do
3534-
{
3535-
LEX_CSTRING save_connect_string= table->s->connect_string;
3536-
if ((error= create_partition_name(name_buff, sizeof(name_buff), name,
3537-
name_buffer_ptr, NORMAL_PART_NAME, FALSE)))
3538-
goto err_handler;
3539-
if (!((*file)->ht->flags & HTON_CAN_READ_CONNECT_STRING_IN_PARTITION))
3540-
table->s->connect_string= m_connect_string[(uint)(file-m_file)];
3541-
error= (*file)->ha_open(table, name_buff, mode,
3542-
test_if_locked | HA_OPEN_NO_PSI_CALL);
3543-
table->s->connect_string= save_connect_string;
3544-
if (error)
3545-
goto err_handler;
3546-
if (m_file == file)
3547-
m_num_locks= (*file)->lock_count();
3548-
DBUG_ASSERT(m_num_locks == (*file)->lock_count());
3549-
name_buffer_ptr+= strlen(name_buffer_ptr) + 1;
3550-
} while (*(++file));
3548+
if ((error= open_read_partitions(name_buff, sizeof(name_buff),
3549+
&file_sample)))
3550+
goto err_handler;
3551+
m_num_locks= file_sample->lock_count();
35513552
}
35523553
/*
35533554
We want to know the upper bound for locks, to allocate enough memory.
@@ -3558,12 +3559,14 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
35583559
m_num_locks*= m_tot_parts;
35593560

35603561
file= m_file;
3561-
ref_length= (*file)->ref_length;
3562-
check_table_flags= (((*file)->ha_table_flags() &
3562+
ref_length= file_sample->ref_length;
3563+
check_table_flags= ((file_sample->ha_table_flags() &
35633564
~(PARTITION_DISABLED_TABLE_FLAGS)) |
35643565
(PARTITION_ENABLED_TABLE_FLAGS));
35653566
while (*(++file))
35663567
{
3568+
if (!bitmap_is_set(&m_opened_partitions, file - m_file))
3569+
continue;
35673570
/* MyISAM can have smaller ref_length for partitions with MAX_ROWS set */
35683571
set_if_bigger(ref_length, ((*file)->ref_length));
35693572
/*
@@ -3580,8 +3583,8 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
35803583
goto err_handler;
35813584
}
35823585
}
3583-
key_used_on_scan= m_file[0]->key_used_on_scan;
3584-
implicit_emptied= m_file[0]->implicit_emptied;
3586+
key_used_on_scan= file_sample->key_used_on_scan;
3587+
implicit_emptied= file_sample->implicit_emptied;
35853588
/*
35863589
Add 2 bytes for partition id in position ref length.
35873590
ref_length=max_in_all_partitions(ref_length) + PARTITION_BYTES_IN_POS
@@ -3612,8 +3615,12 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
36123615

36133616
err_handler:
36143617
DEBUG_SYNC(ha_thd(), "partition_open_error");
3618+
file= &m_file[m_tot_parts - 1];
36153619
while (file-- != m_file)
3616-
(*file)->ha_close();
3620+
{
3621+
if (bitmap_is_set(&m_opened_partitions, file - m_file))
3622+
(*file)->ha_close();
3623+
}
36173624
err_alloc:
36183625
free_partition_bitmaps();
36193626
my_free(m_range_info);
@@ -3744,7 +3751,6 @@ int ha_partition::close(void)
37443751
DBUG_ASSERT(m_part_info);
37453752

37463753
destroy_record_priority_queue();
3747-
free_partition_bitmaps();
37483754

37493755
for (; ft_first ; ft_first= tmp_ft_info)
37503756
{
@@ -3795,9 +3801,12 @@ int ha_partition::close(void)
37953801
repeat:
37963802
do
37973803
{
3798-
(*file)->ha_close();
3804+
if (!first || bitmap_is_set(&m_opened_partitions, file - m_file))
3805+
(*file)->ha_close();
37993806
} while (*(++file));
38003807

3808+
free_partition_bitmaps();
3809+
38013810
if (first && m_added_file && m_added_file[0])
38023811
{
38033812
file= m_added_file;
@@ -8246,15 +8255,18 @@ int ha_partition::info(uint flag)
82468255
do
82478256
{
82488257
file= *file_array;
8249-
/* Get variables if not already done */
8250-
if (!(flag & HA_STATUS_VARIABLE) ||
8251-
!bitmap_is_set(&(m_part_info->read_partitions),
8252-
(uint)(file_array - m_file)))
8253-
file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag);
8254-
if (file->stats.records > max_records)
8258+
if (bitmap_is_set(&(m_opened_partitions), (file_array - m_file)))
82558259
{
8256-
max_records= file->stats.records;
8257-
handler_instance= i;
8260+
/* Get variables if not already done */
8261+
if (!(flag & HA_STATUS_VARIABLE) ||
8262+
!bitmap_is_set(&(m_part_info->read_partitions),
8263+
(uint) (file_array - m_file)))
8264+
file->info(HA_STATUS_VARIABLE | no_lock_flag | extra_var_flag);
8265+
if (file->stats.records > max_records)
8266+
{
8267+
max_records= file->stats.records;
8268+
handler_instance= i;
8269+
}
82588270
}
82598271
i++;
82608272
} while (*(++file_array));
@@ -8335,6 +8347,96 @@ void ha_partition::get_dynamic_partition_info(PARTITION_STATS *stat_info,
83358347
}
83368348

83378349

8350+
void ha_partition::set_partitions_to_open(List<String> *partition_names)
8351+
{
8352+
m_partitions_to_open= partition_names;
8353+
}
8354+
8355+
8356+
int ha_partition::open_read_partitions(char *name_buff, size_t name_buff_size,
8357+
handler **sample)
8358+
{
8359+
handler **file;
8360+
char *name_buffer_ptr;
8361+
int error;
8362+
8363+
name_buffer_ptr= m_name_buffer_ptr;
8364+
file= m_file;
8365+
*sample= NULL;
8366+
do
8367+
{
8368+
int n_file= file-m_file;
8369+
int is_open= bitmap_is_set(&m_opened_partitions, n_file);
8370+
int should_be_open= bitmap_is_set(&m_part_info->read_partitions, n_file);
8371+
8372+
if (is_open && !should_be_open)
8373+
{
8374+
if ((error= (*file)->ha_close()))
8375+
goto err_handler;
8376+
bitmap_clear_bit(&m_opened_partitions, n_file);
8377+
}
8378+
else if (!is_open && should_be_open)
8379+
{
8380+
LEX_CSTRING save_connect_string= table->s->connect_string;
8381+
if ((error= create_partition_name(name_buff, name_buff_size,
8382+
table->s->normalized_path.str,
8383+
name_buffer_ptr, NORMAL_PART_NAME, FALSE)))
8384+
goto err_handler;
8385+
if (!((*file)->ht->flags & HTON_CAN_READ_CONNECT_STRING_IN_PARTITION))
8386+
table->s->connect_string= m_connect_string[(uint)(file-m_file)];
8387+
error= (*file)->ha_open(table, name_buff, m_mode,
8388+
m_open_test_lock | HA_OPEN_NO_PSI_CALL);
8389+
table->s->connect_string= save_connect_string;
8390+
if (error)
8391+
goto err_handler;
8392+
if (!(*sample))
8393+
*sample= *file;
8394+
bitmap_set_bit(&m_opened_partitions, n_file);
8395+
}
8396+
name_buffer_ptr+= strlen(name_buffer_ptr) + 1;
8397+
} while (*(++file));
8398+
8399+
err_handler:
8400+
return error;
8401+
}
8402+
8403+
8404+
int ha_partition::change_partitions_to_open(List<String> *partition_names)
8405+
{
8406+
char name_buff[FN_REFLEN+1];
8407+
int error= 0;
8408+
handler *sample;
8409+
8410+
if (m_is_clone_of)
8411+
return 0;
8412+
8413+
m_partitions_to_open= partition_names;
8414+
if ((error= m_part_info->set_partition_bitmaps(partition_names)))
8415+
goto err_handler;
8416+
8417+
if (m_lock_type != F_UNLCK)
8418+
{
8419+
/*
8420+
That happens after the LOCK TABLE statement.
8421+
Do nothing in this case.
8422+
*/
8423+
return 0;
8424+
}
8425+
8426+
if (bitmap_cmp(&m_opened_partitions, &m_part_info->read_partitions) != 0)
8427+
return 0;
8428+
8429+
if ((error= read_par_file(table->s->normalized_path.str)) ||
8430+
(error= open_read_partitions(name_buff, sizeof(name_buff), &sample)))
8431+
goto err_handler;
8432+
8433+
clear_handler_file();
8434+
8435+
err_handler:
8436+
return error;
8437+
}
8438+
8439+
83388440
/**
83398441
General function to prepare handler for certain behavior.
83408442
@@ -8831,7 +8933,8 @@ int ha_partition::reset(void)
88318933
i < m_tot_parts;
88328934
i= bitmap_get_next_set(&m_partitions_to_reset, i))
88338935
{
8834-
if ((tmp= m_file[i]->ha_reset()))
8936+
if (bitmap_is_set(&m_opened_partitions, i) &&
8937+
(tmp= m_file[i]->ha_reset()))
88358938
result= tmp;
88368939
}
88378940
bitmap_clear_all(&m_partitions_to_reset);
@@ -8948,7 +9051,12 @@ int ha_partition::loop_extra(enum ha_extra_function operation)
89489051
i < m_tot_parts;
89499052
i= bitmap_get_next_set(&m_part_info->lock_partitions, i))
89509053
{
8951-
if ((tmp= m_file[i]->extra(operation)))
9054+
/*
9055+
This can be called after an error in ha_open.
9056+
In this case calling 'extra' can crash.
9057+
*/
9058+
if (bitmap_is_set(&m_opened_partitions, i) &&
9059+
(tmp= m_file[i]->extra(operation)))
89529060
result= tmp;
89539061
}
89549062
/* Add all used partitions to be called in reset(). */

sql/ha_partition.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,8 @@ class ha_partition :public handler
385385
/** partitions that returned HA_ERR_KEY_NOT_FOUND. */
386386
MY_BITMAP m_key_not_found_partitions;
387387
bool m_key_not_found;
388+
List<String> *m_partitions_to_open;
389+
MY_BITMAP m_opened_partitions;
388390
public:
389391
handler **get_child_handlers()
390392
{
@@ -836,6 +838,10 @@ class ha_partition :public handler
836838
virtual int info(uint);
837839
void get_dynamic_partition_info(PARTITION_STATS *stat_info,
838840
uint part_id);
841+
void set_partitions_to_open(List<String> *partition_names);
842+
int change_partitions_to_open(List<String> *partition_names);
843+
int open_read_partitions(char *name_buff, size_t name_buff_size,
844+
handler **sample);
839845
virtual int extra(enum ha_extra_function operation);
840846
virtual int extra_opt(enum ha_extra_function operation, ulong cachesize);
841847
virtual int reset(void);

0 commit comments

Comments
 (0)