diff options
author | Monty <monty@mariadb.org> | 2023-02-10 13:18:39 +0200 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2023-03-02 13:11:54 +0200 |
commit | bd9ca2a0e3dfb00da226822cea53bb856e8393f0 (patch) | |
tree | e7ce21d5f51c1ea255485d0f3ea012ff6116c0fa /sql/table.cc | |
parent | eb441f6cb7f32caeba4ea1633e8111318b0a2574 (diff) | |
download | mariadb-git-bd9ca2a0e3dfb00da226822cea53bb856e8393f0.tar.gz |
MDEV-30540 Wrong result with IN list length reaching IN_PREDICATE_CONVERSION_THRESHOLD
The problem was the mysql_derived_prepare() did not correctly set
'distinct' when creating a temporary derivated table.
Fixed by separating checking for distinct for queries with and without
UNION.
Other things:
- Fixed bug in generate_derived_keys_for_table() where we set the wrong
bit for join_tab->keys
- Cleaned up JOIN::drop_unused_derived_keys()
- Changed TABLE::use_index() to keep unique keys and update
share->key_parts
Author: Sergei Petrunia <sergey@mariadb.com>, monty@mariadb.org
Diffstat (limited to 'sql/table.cc')
-rw-r--r-- | sql/table.cc | 61 |
1 files changed, 46 insertions, 15 deletions
diff --git a/sql/table.cc b/sql/table.cc index e0189401906..9ba9817d587 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -8208,7 +8208,7 @@ void TABLE::restore_blob_values(String *blob_storage) @param key_count number of keys to allocate additionally @details - The function allocates memory to fit additionally 'key_count' keys + The function allocates memory to fit additionally 'key_count' keys for this table. @return FALSE space was successfully allocated @@ -8472,28 +8472,59 @@ bool TABLE::add_tmp_key(uint key, uint key_parts, /* @brief - Drop all indexes except specified one. + Drop all indexes except specified one and optionally unique keys. - @param key_to_save the key to save + @param key_to_save The key to save + @param map_to_update Bitmap showing some of the table's keys. Update it + to show the same keys, if they are not dropped. + @param unique_keys Keep unique keys @details - Drop all indexes on this table except 'key_to_save'. The saved key becomes - key #0. Memory occupied by key parts of dropped keys are freed. - If the 'key_to_save' is negative then all keys are freed. + Drop all indexes on this table except 'key_to_save' and unique keys. + + The saved key becomes key #0. If key_to_save=-1 then only unique keys + remain. */ -void TABLE::use_index(int key_to_save) +void TABLE::use_index(int key_to_save, key_map *map_to_update) { - uint i= 1; DBUG_ASSERT(!created && key_to_save < (int)s->keys); - if (key_to_save >= 0) - /* Save the given key. */ - memmove(key_info, key_info + key_to_save, sizeof(KEY)); - else - /* Drop all keys; */ - i= 0; + uint saved_keys= 0, key_parts= 0; + key_map new_bitmap; + new_bitmap.clear_all(); + + /* + If we have key_to_save, move it to be key#0. + */ + if (key_to_save != -1) + { + new_bitmap.set_bit(saved_keys); + + KEY tmp_buff= key_info[saved_keys]; + key_info[saved_keys]= key_info[key_to_save]; + key_info[key_to_save]= tmp_buff; + key_parts= key_info[saved_keys].user_defined_key_parts; + saved_keys++; + } - s->keys= i; + /* + Now, move all unique keys to the front. + */ + for (uint i= saved_keys; i < s->keys; i++) + { + if (key_info[i].flags & HA_NOSAME) + { + if (map_to_update->is_set(i)) + new_bitmap.set_bit(saved_keys); + if (i != saved_keys) + key_info[saved_keys]= key_info[i]; + key_parts+= key_info[saved_keys].user_defined_key_parts; + saved_keys++; + } + } + *map_to_update= new_bitmap; + s->keys= saved_keys; + s->key_parts= s->ext_key_parts= key_parts; } /* |