@@ -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
34383444int 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
36133616err_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+ }
36173624err_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)
37953801repeat:
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(). */
0 commit comments