summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/handler.cc14
-rw-r--r--sql/handler.h14
-rw-r--r--sql/sql_table.cc118
3 files changed, 83 insertions, 63 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index aa3815b2de3..77b7f490590 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -6953,6 +6953,20 @@ void handler::set_lock_type(enum thr_lock_type lock)
table->reginfo.lock_type= lock;
}
+Compare_keys handler::compare_key_parts(const Field &old_field,
+ const Column_definition &new_field,
+ const KEY_PART_INFO &old_part,
+ const KEY_PART_INFO &new_part) const
+{
+ if (!old_field.is_equal(new_field))
+ return Compare_keys::NotEqual;
+
+ if (old_part.length != new_part.length)
+ return Compare_keys::NotEqual;
+
+ return Compare_keys::Equal;
+}
+
#ifdef WITH_WSREP
/**
@details
diff --git a/sql/handler.h b/sql/handler.h
index 6d675683ada..421941c0b35 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -2936,6 +2936,13 @@ public:
virtual ~Handler_share() {}
};
+enum class Compare_keys : uint32_t
+{
+ Equal,
+ EqualButKeyPartLength,
+ EqualButComment,
+ NotEqual
+};
/**
The handler class is the interface for dynamically loadable
@@ -4877,6 +4884,13 @@ public:
return false;
}
+ /* Used for ALTER TABLE.
+ Some engines can handle some differences in indexes by themself. */
+ virtual Compare_keys compare_key_parts(const Field &old_field,
+ const Column_definition &new_field,
+ const KEY_PART_INFO &old_part,
+ const KEY_PART_INFO &new_part) const;
+
protected:
Handler_share *get_ha_share_ptr();
void set_ha_share_ptr(Handler_share *arg_ha_share);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 851a63bf05a..619c3fe2654 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -6579,38 +6579,68 @@ static int compare_uint(const uint *s, const uint *t)
return (*s < *t) ? -1 : ((*s > *t) ? 1 : 0);
}
-enum class Compare_keys : uint32_t
-{
- Equal,
- EqualButKeyPartLength,
- EqualButComment,
- NotEqual
-};
+static Compare_keys merge(Compare_keys current, Compare_keys add) {
+ if (current == Compare_keys::Equal)
+ return add;
+
+ if (add == Compare_keys::Equal)
+ return current;
+
+ if (current == add)
+ return current;
+
+ if (current == Compare_keys::EqualButComment) {
+ return Compare_keys::NotEqual;
+ }
+
+ if (current == Compare_keys::EqualButKeyPartLength) {
+ if (add == Compare_keys::EqualButComment)
+ return Compare_keys::NotEqual;
+ DBUG_ASSERT(add == Compare_keys::NotEqual);
+ return Compare_keys::NotEqual;
+ }
+
+ DBUG_ASSERT(current == Compare_keys::NotEqual);
+ return current;
+}
Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
Alter_info *alter_info, const TABLE *table,
const KEY *const new_pk,
const KEY *const old_pk)
{
- Compare_keys result= Compare_keys::Equal;
+ if (table_key->algorithm != new_key->algorithm)
+ return Compare_keys::NotEqual;
+
+ if ((table_key->flags & HA_KEYFLAG_MASK) !=
+ (new_key->flags & HA_KEYFLAG_MASK))
+ return Compare_keys::NotEqual;
- if ((table_key->algorithm != new_key->algorithm) ||
- ((table_key->flags & HA_KEYFLAG_MASK) !=
- (new_key->flags & HA_KEYFLAG_MASK)) ||
- (table_key->user_defined_key_parts != new_key->user_defined_key_parts))
+ if (table_key->user_defined_key_parts != new_key->user_defined_key_parts)
return Compare_keys::NotEqual;
if (table_key->block_size != new_key->block_size)
return Compare_keys::NotEqual;
+ /*
+ Rebuild the index if following condition get satisfied:
+
+ (i) Old table doesn't have primary key, new table has it and vice-versa
+ (ii) Primary key changed to another existing index
+ */
+ if ((new_key == new_pk) != (table_key == old_pk))
+ return Compare_keys::NotEqual;
+
if (engine_options_differ(table_key->option_struct, new_key->option_struct,
table->file->ht->index_options))
return Compare_keys::NotEqual;
- const KEY_PART_INFO *end=
- table_key->key_part + table_key->user_defined_key_parts;
- for (const KEY_PART_INFO *key_part= table_key->key_part,
- *new_part= new_key->key_part;
+ Compare_keys result= Compare_keys::Equal;
+
+ for (const KEY_PART_INFO *
+ key_part= table_key->key_part,
+ *new_part= new_key->key_part,
+ *end= table_key->key_part + table_key->user_defined_key_parts;
key_part < end; key_part++, new_part++)
{
/*
@@ -6618,61 +6648,23 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
object with adjusted length. So below we have to check field
indexes instead of simply comparing pointers to Field objects.
*/
- Create_field *new_field= alter_info->create_list.elem(new_part->fieldnr);
- if (!new_field->field ||
- new_field->field->field_index != key_part->fieldnr - 1)
- return Compare_keys::NotEqual;
-
- /*
- If there is a change in index length due to column expansion
- like varchar(X) changed to varchar(X + N) and has a compatible
- packed data representation, we mark it for fast/INPLACE change
- in index definition. InnoDB supports INPLACE for this cases
-
- Key definition has changed if we are using a different field or
- if the user key part length is different.
- */
- const Field *old_field= table->field[key_part->fieldnr - 1];
+ const Create_field &new_field=
+ *alter_info->create_list.elem(new_part->fieldnr);
- bool is_equal= old_field->is_equal(*new_field);
- /* TODO: below is an InnoDB specific code which should be moved to InnoDB */
- if (!is_equal)
+ if (!new_field.field ||
+ new_field.field->field_index != key_part->fieldnr - 1)
{
- if (!key_part->field->can_be_converted_by_engine(*new_field))
- return Compare_keys::NotEqual;
-
- if (!Charset(old_field->charset())
- .eq_collation_specific_names(new_field->charset))
- return Compare_keys::NotEqual;
+ return Compare_keys::NotEqual;
}
- if (key_part->length != new_part->length)
- {
- if (key_part->length != old_field->field_length ||
- key_part->length >= new_part->length || is_equal)
- {
- return Compare_keys::NotEqual;
- }
- result= Compare_keys::EqualButKeyPartLength;
- }
+ auto compare= table->file->compare_key_parts(
+ *table->field[key_part->fieldnr - 1], new_field, *key_part, *new_part);
+ result= merge(result, compare);
}
- /*
- Rebuild the index if following condition get satisfied:
-
- (i) Old table doesn't have primary key, new table has it and vice-versa
- (ii) Primary key changed to another existing index
-*/
- if ((new_key == new_pk) != (table_key == old_pk))
- return Compare_keys::NotEqual;
-
/* Check that key comment is not changed. */
if (cmp(table_key->comment, new_key->comment) != 0)
- {
- if (result != Compare_keys::Equal)
- return Compare_keys::NotEqual;
- result= Compare_keys::EqualButComment;
- }
+ result= merge(result, Compare_keys::EqualButComment);
return result;
}