diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 13d7665..4a77afc 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -645,9 +649,20 @@ end: derive which partitions are needed to scan. */ -static void clear_indicator_in_key_fields(KEY *key_info) { +static void clear_indicator_in_key_fields(KEY *key_info, uint actual_used_key_parts = 0) { KEY_PART_INFO *key_part; uint key_parts = key_info->user_defined_key_parts, i; + + if (actual_used_key_parts != 0 && + actual_used_key_parts > key_info->user_defined_key_parts) + key_parts = actual_used_key_parts; + for (i = 0, key_part = key_info->key_part; i < key_parts; i++, key_part++) key_part->field->clear_flag(GET_FIXED_FIELDS_FLAG); } @@ -3584,13 +3599,21 @@ static int get_partition_id_linear_key_sub(partition_info *part_info, set_PF_fields_in_key() key_info Information about the index key_length Length of key + actual_used_key_parts[out] the num of actual used key parts, maybe larger than user_defined_key_parts RETURN VALUE true Found partition field set by key false No partition field set by key */ -static bool set_PF_fields_in_key(KEY *key_info, uint key_length) { +static bool set_PF_fields_in_key(KEY *key_info, uint key_length, uint &actual_used_key_parts) { KEY_PART_INFO *key_part; bool found_part_field = false; DBUG_TRACE; @@ -3609,6 +3632,9 @@ static bool set_PF_fields_in_key(KEY *key_info, uint key_length) { found_part_field = true; key_part->field->set_flag(GET_FIXED_FIELDS_FLAG); } + actual_used_key_parts++; } return found_part_field; } @@ -3922,6 +3969,9 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index, uint32 part_part = num_parts; KEY *key_info = nullptr; bool found_part_field = false; + uint actual_used_key_parts = 0; DBUG_TRACE; part_spec->start_part = 0; @@ -3982,29 +4032,38 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index, */ + /* + Before the following bugs are fixed, error log will be printed in + check_indicator_clear_in_part_fields(): + 1. Bug #97041 main&sub partition field order different from combined + pk, query result lose row. + + 2. GET_FIXED_FIELDS_FLAG flag is set in set_PF_fields_in_key() but + not cleared in original clear_indicator_in_key_fields() because + original clear_indicator_in_key_fields() only clear user defined key + parts and there are hidden parts in a secondary key that are not + cleared. So a bug occurs and wrong partition is fetched when another + sql use the same TABLE. + */ + check_indicator_clear_in_part_fields(table, part_info->full_part_field_array); if ((found_part_field = - set_PF_fields_in_key(key_info, key_spec->length))) { + set_PF_fields_in_key(key_info, key_spec->length, actual_used_key_parts /* output */ ))) { if (check_part_func_bound(part_info->full_part_field_array)) { /* We were able to bind all fields in the partition function even by using only a part of the key. Calculate the partition to use. */ get_full_part_id_from_key(table, buf, key_info, key_spec, part_spec); - clear_indicator_in_key_fields(key_info); + clear_indicator_in_key_fields(key_info, actual_used_key_parts); /* Check if range can be adjusted by looking in read_partitions */ @@ -4015,14 +4074,22 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index, if (get_sub_part_id_from_key(table, buf, key_info, key_spec, &sub_part)) { part_spec->start_part = num_parts; - clear_indicator_in_key_fields(key_info); + clear_indicator_in_key_fields(key_info, actual_used_key_parts); return; } } else if (check_part_func_bound(part_info->part_field_array)) { if (get_part_id_from_key(table, buf, key_info, key_spec, &part_part)) { part_spec->start_part = num_parts; - clear_indicator_in_key_fields(key_info); + clear_indicator_in_key_fields(key_info, actual_used_key_parts); return; } } @@ -4064,7 +4131,11 @@ void get_partition_set(const TABLE *table, uchar *buf, const uint index, ; // Set bit part_id in bit array } } - if (found_part_field) clear_indicator_in_key_fields(key_info); + if (found_part_field) clear_indicator_in_key_fields(key_info, actual_used_key_parts); /* Check if range can be adjusted by looking in read_partitions */