From: Patrick Galbraith Date: December 16 2005 1:25pm Subject: bk commit into 5.1 tree (patg:1.1961) List-Archive: http://lists.mysql.com/commits/202 Message-Id: <20051216132532.A3268C262C@krsna.patg.net> Below is the list of changes that have just been committed into a local 5.1 repository of patg. When patg does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.1961 05/12/16 05:25:19 patg@stripped +3 -0 wl# 2682 Changes to test if a partition specified in a query exists by using a HASH member of the share, as well as adding the bitmap used_partitions to the handler class sql/handler.h 1.172 05/12/16 05:25:11 patg@stripped +3 -1 wl# 2682 Added used_partitions bitmap sql/ha_partition.h 1.7 05/12/16 05:25:11 patg@stripped +9 -0 New struct st_partition_name - a record to store in a hash keyed by partition names. sql/ha_partition.cc 1.13 05/12/16 05:25:11 patg@stripped +96 -2 wl# 2682 - Add share->partition_names HASH to share. This is a HASH object to store a parition_name struct that has partition_name, number, name length and is_sub_partition bool. The reason for a HASH is for quick lookups to verify a given subpartition in 'SELECT * FROM foo PARTITION (foo)" exists. Also added is_partition_in table to return bool of whether the partition is in the table. Made sure all hash members are deleted in ::close, but still need to figure out how to free share->partition_names Using the call to is_partition_in_table in external_lock and throwing an error if not works just fine! # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: patg # Host: krsna.patg.net # Root: /home/patg/mysql-build/mysql-5.1-wl2682 --- 1.171/sql/handler.h 2005-12-13 12:14:45 -08:00 +++ 1.172/sql/handler.h 2005-12-16 05:25:11 -08:00 @@ -555,7 +555,9 @@ longlong *range_int_array; LIST_PART_ENTRY *list_array; }; - char* part_info_string; + + MY_BITMAP *used_partitions; + char *part_info_string; char *part_func_string; char *subpart_func_string; --- 1.12/sql/ha_partition.cc 2005-11-25 20:17:12 -08:00 +++ 1.13/sql/ha_partition.cc 2005-12-16 05:25:11 -08:00 @@ -62,6 +62,26 @@ static PARTITION_SHARE *get_share(const char *table_name, TABLE * table); #endif +static byte *partition_names_get_key(PARTITION_NAME *partition_name, uint *length, + my_bool not_used __attribute__ ((unused))) +{ + *length= partition_name->partition_name_length; + return (byte *) partition_name->partition_name; +} + +bool is_partition_in_table(PARTITION_SHARE *share, char *name) +{ + PARTITION_NAME *partition_name; + DBUG_ENTER("is_partition_in_table"); + partition_name= (PARTITION_NAME*)hash_search(&share->partition_names, + (byte*) name, + strlen(name)); + if (partition_name && partition_name->partition_name) + DBUG_RETURN(1); + + DBUG_RETURN(0); +} + /**************************************************************************** MODULE create/delete handler object ****************************************************************************/ @@ -863,12 +883,15 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) { - int error; char name_buff[FN_REFLEN]; char *name_buffer_ptr= m_name_buffer_ptr; + int error; + uint alloc_len,i, j, part_num_counter= 0; handler **file; - uint alloc_len; + List_iterator_fast part_it(m_part_info->partitions); DBUG_ENTER("ha_partition::open"); + (void) hash_init(&share->partition_names, system_charset_info, 32, 0, 0, + (hash_get_key) partition_names_get_key, 0, 0); ref_length= 0; m_part_field_array= m_part_info->full_part_field_array; @@ -903,6 +926,39 @@ m_start_key.key= (const byte*)ptr; } } + for (i= 0; i < m_part_info->no_parts; i++) + { + PARTITION_NAME *partition_name = (PARTITION_NAME*)my_malloc(sizeof(PARTITION_NAME), MYF(MY_WME)); + partition_element *part_elem= part_it++; + partition_name->partition_name= part_elem->partition_name; + partition_name->partition_name_length= strlen(part_elem->partition_name); + partition_name->partition_number=part_num_counter++; + partition_name->is_sub_partition= FALSE; + if (my_hash_insert(&share->partition_names, (byte *)partition_name)) + goto err_handler; + if (is_sub_partitioned(m_part_info)) + { + List_iterator sub_it(part_elem->subpartitions); + for (j= 0; j < m_part_info->no_subparts; j++) + { + partition_element *sub_elem= sub_it++; + if (!strcmp(sub_elem->partition_name, part_elem->partition_name)) + { + PARTITION_NAME *sub_partition_name = + (PARTITION_NAME*)my_malloc(sizeof(PARTITION_NAME), MYF(MY_WME)); + sub_partition_name->partition_name= sub_elem->partition_name; + sub_partition_name->partition_name_length= strlen(sub_elem->partition_name); + sub_partition_name->partition_number=part_num_counter++; + sub_partition_name->is_sub_partition= TRUE; + } + else + { + continue; + } + } + } + DBUG_PRINT("info", ("partition name %s", part_elem->partition_name)); + } file= m_file; do { @@ -914,6 +970,7 @@ name_buffer_ptr+= strlen(name_buffer_ptr) + 1; set_if_bigger(ref_length, ((*file)->ref_length)); } while (*(++file)); + /* Add 2 bytes for partition id in position ref length. ref_length=max_in_all_partitions(ref_length) + PARTITION_BYTES_IN_POS @@ -931,6 +988,9 @@ if ((error= init_queue(&queue, m_tot_parts, (uint) PARTITION_BYTES_IN_POS, 0, key_rec_cmp, (void*)this))) goto err_handler; + + + /* Some handlers update statistics as part of the open call. This will in some cases corrupt the statistics of the partition handler and thus @@ -960,12 +1020,21 @@ int ha_partition::close(void) { handler **file; + List_iterator_fast part_it(m_part_info->partitions); DBUG_ENTER("ha_partition::close"); delete_queue(&queue); file= m_file; do { + PARTITION_NAME *partition_name; + partition_element *part_elem= part_it++; + partition_name= (PARTITION_NAME*)hash_search(&share->partition_names, + (byte*) part_elem->partition_name, + strlen(part_elem->partition_name)); + VOID(hash_delete(&share->partition_names, (byte*)partition_name)); + DBUG_PRINT("info", ("partition_name->partition_name %s", partition_name->partition_name)); + my_free((gptr) partition_name, MYF(0)); (*file)->close(); } while (*(++file)); DBUG_RETURN(0); @@ -1004,12 +1073,32 @@ { uint error; handler **file; + uint i; + bool is_in_list; + List_iterator_fast part_it(m_part_info->partitions); DBUG_ENTER("ha_partition::external_lock"); + if (thd->lex->part_info) + { + uint retval=0; + retval= is_partition_in_table(share, thd->lex->part_info->selected_partition); + if (retval) + { + DBUG_PRINT("info", ("selected partition %s is in table", + thd->lex->part_info->selected_partition)); + } + else + { + my_error(ER_NO_SUCH_PARTITION, MYF(0), + thd->lex->part_info->selected_partition); + } + } + DBUG_PRINT("info", ("is_in_list %d", is_in_list)); file= m_file; do { if ((error= (*file)->external_lock(thd, lock_type))) { + DBUG_PRINT("info", ("(file)->s->table_name.str", (*file)->table_share->table_name.str)); if (lock_type != F_UNLCK) goto err_handler; } @@ -3261,6 +3350,11 @@ hash_delete(&partition_open_tables, (byte *) share); thr_lock_delete(&share->lock); pthread_mutex_destroy(&share->mutex); + /* + this doesn't seem to free share->partition_names, + need to know how to make sure this happens + */ + my_free((gptr) &share->partition_names, MYF(0)); my_free((gptr) share, MYF(0)); } pthread_mutex_unlock(&partition_mutex); --- 1.6/sql/ha_partition.h 2005-11-25 00:08:30 -08:00 +++ 1.7/sql/ha_partition.h 2005-12-16 05:25:11 -08:00 @@ -28,8 +28,17 @@ char *table_name; uint table_name_length, use_count; pthread_mutex_t mutex; + HASH partition_names; THR_LOCK lock; } PARTITION_SHARE; + +typedef struct st_partition_name +{ + char *partition_name; + bool is_sub_partition; + uint partition_name_length; + uint partition_number; +} PARTITION_NAME; #define PARTITION_BYTES_IN_POS 2