← Back to team overview

maria-developers team mailing list archive

Re: e752eed5354: MDEV-19751 Wrong partitioning by KEY() after key dropped

 

Hi, Aleksey!

On Oct 29, Aleksey Midenkov wrote:
> revision-id: e752eed5354 (mariadb-10.4.7-47-ge752eed5354)
> parent(s): 8403148452a
> author: Aleksey Midenkov <midenok@xxxxxxxxx>
> committer: Aleksey Midenkov <midenok@xxxxxxxxx>
> timestamp: 2019-08-19 12:00:13 +0300
> message:
> 
> MDEV-19751 Wrong partitioning by KEY() after key dropped
> 
> Empty partition by key() clause implies that key might be changed by
> ALTER, but inplace algorithm must not be used since repartitioning is
> required for a different key.

good and very clear comment.
 
> diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
> index 10b9c74d868..d76ff5e2e76 100644
> --- a/sql/sql_partition.cc
> +++ b/sql/sql_partition.cc
> @@ -5903,6 +5903,45 @@ the generated partition syntax in a correct manner.
>            *partition_changed= TRUE;
>          }
>        }
> +      /*
> +        Prohibit inplace when key takes part in partitioning expression
> +        and is altered (dropped).
> +      */
> +      if (!*partition_changed && tab_part_info->part_field_array)
> +      {
> +        KEY *key_info= table->key_info;
> +        List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list);
> +        for (uint key= 0; key < table->s->keys; key++, key_info++)
> +        {
> +          if (key_info->flags & HA_INVISIBLE_KEY)
> +            continue;
> +          const char *key_name= key_info->name.str;
> +          const Alter_drop *drop;
> +          drop_it.rewind();
> +          while ((drop= drop_it++))
> +          {
> +            if (drop->type == Alter_drop::KEY &&
> +                0 == my_strcasecmp(system_charset_info, key_name, drop->name))
> +              break;
> +          }
> +          if (!drop)
> +            continue;
> +          for (uint kp= 0; kp < key_info->user_defined_key_parts; ++kp)
> +          {
> +            const KEY_PART_INFO &key_part= key_info->key_part[kp];
> +            for (Field **part_field= tab_part_info->part_field_array;
> +                *part_field; ++part_field)
> +            {
> +              if (*part_field == key_part.field)
> +              {
> +                *partition_changed= TRUE;
> +                goto search_finished;
> +              }
> +            } // for (part_field)
> +          } // for (key_part)
> +        } // for (key_info)

Hmm, if I read it correctly, you iterate over all key parts of every
dropped key and see if this field is also part of the partitioning
expression.

This sounds kind of strange. What if there are two indexes that use the
column `a`, say

  CREATE TABLE t1 (a int, b int, index(a), index(b,a))

and you partition by key(a). Dropping the second index does not change
the partitioning, does it?

On the other hand, if it's ALTER TABLE ... MODIFY `a` then it can change
partitioning, even when the key hasn't changed, right?

So, I suspect your check is too strong in some cases and too loose is
others.

> +        search_finished:;
> +      }
>      }
>      if (thd->work_part_info)
>      {
> diff --git a/storage/connect/mysql-test/connect/r/part_file.result b/storage/connect/mysql-test/connect/r/part_file.result
> index 3dabd946b50..480de51cce6 100644
> --- a/storage/connect/mysql-test/connect/r/part_file.result
> +++ b/storage/connect/mysql-test/connect/r/part_file.result
> @@ -308,12 +308,19 @@ EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
>  id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	Extra
>  1	SIMPLE	t1	1	ref	XID	XID	4	const	1	
>  DROP INDEX XID ON t1;
> +Warnings:
> +Warning	1105	Data repartition in 1 is unchecked
> +Warning	1105	Data repartition in 2 is unchecked
> +Warning	1105	Data repartition in 3 is unchecked

why did the result file change?
could you add a short explanation of it to the commit comment, please?

Regards,
Sergei
VP of MariaDB Server Engineering
and security@xxxxxxxxxxx