MDEV-29495 Generalize can_convert_xxx() hook engine API to cover any arbitrary data type

This commit is contained in:
Alexander Barkov 2022-10-26 14:48:03 +04:00
parent 29633dc0c0
commit ce443c8554
7 changed files with 43 additions and 87 deletions

View file

@ -1552,12 +1552,6 @@ public:
Used by the ALTER TABLE
*/
virtual bool is_equal(const Column_definition &new_field) const= 0;
// Used as double dispatch pattern: calls virtual method of handler
virtual bool
can_be_converted_by_engine(const Column_definition &new_type) const
{
return false;
}
/* convert decimal to longlong with overflow check */
longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
int *err);
@ -3621,10 +3615,6 @@ public:
void sql_type(String &str) const;
void sql_rpl_type(String*) const;
bool is_equal(const Column_definition &new_field) const;
bool can_be_converted_by_engine(const Column_definition &new_type) const
{
return table->file->can_convert_string(this, new_type);
}
virtual uchar *pack(uchar *to, const uchar *from,
uint max_length);
virtual const uchar *unpack(uchar* to, const uchar *from,
@ -3751,10 +3741,6 @@ public:
uchar *new_ptr, uint32 length,
uchar *new_null_ptr, uint new_null_bit);
bool is_equal(const Column_definition &new_field) const;
bool can_be_converted_by_engine(const Column_definition &new_type) const
{
return table->file->can_convert_varstring(this, new_type);
}
void hash(ulong *nr, ulong *nr2);
uint length_size() const { return length_bytes; }
void print_key_value(String *out, uint32 length);
@ -4128,10 +4114,6 @@ public:
uint32 char_length() const;
uint32 character_octet_length() const;
bool is_equal(const Column_definition &new_field) const;
bool can_be_converted_by_engine(const Column_definition &new_type) const
{
return table->file->can_convert_blob(this, new_type);
}
void print_key_value(String *out, uint32 length);
friend void TABLE::remember_blob_values(String *blob_storage);
@ -4247,10 +4229,6 @@ public:
!table->copy_blobs;
}
bool is_equal(const Column_definition &new_field) const;
bool can_be_converted_by_engine(const Column_definition &new_type) const
{
return table->file->can_convert_geom(this, new_type);
}
int store(const char *to, size_t length, CHARSET_INFO *charset);
int store(double nr);

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2005, 2019, Oracle and/or its affiliates.
Copyright (c) 2009, 2021, MariaDB
Copyright (c) 2009, 2022, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -12021,35 +12021,12 @@ void ha_partition::clear_top_table_fields()
}
bool
ha_partition::can_convert_string(const Field_string* field,
const Column_definition& new_type) const
ha_partition::can_convert_nocopy(const Field &field,
const Column_definition &new_type) const
{
for (uint index= 0; index < m_tot_parts; index++)
{
if (!m_file[index]->can_convert_string(field, new_type))
return false;
}
return true;
}
bool
ha_partition::can_convert_varstring(const Field_varstring* field,
const Column_definition& new_type) const{
for (uint index= 0; index < m_tot_parts; index++)
{
if (!m_file[index]->can_convert_varstring(field, new_type))
return false;
}
return true;
}
bool
ha_partition::can_convert_blob(const Field_blob* field,
const Column_definition& new_type) const
{
for (uint index= 0; index < m_tot_parts; index++)
{
if (!m_file[index]->can_convert_blob(field, new_type))
if (!m_file[index]->can_convert_nocopy(field, new_type))
return false;
}
return true;

View file

@ -1624,16 +1624,8 @@ public:
friend int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2);
friend int cmp_key_part_id(void *key_p, uchar *ref1, uchar *ref2);
bool can_convert_string(
const Field_string* field,
const Column_definition& new_field) const override;
bool can_convert_varstring(
const Field_varstring* field,
const Column_definition& new_field) const override;
bool can_convert_blob(
const Field_blob* field,
const Column_definition& new_field) const override;
bool can_convert_nocopy(const Field &field,
const Column_definition &new_field) const override;
};
#endif /* HA_PARTITION_INCLUDED */

View file

@ -4851,23 +4851,8 @@ public:
These functions check for such possibility.
Implementation could be based on Field_xxx::is_equal()
*/
virtual bool can_convert_string(const Field_string *field,
const Column_definition &new_type) const
{
return false;
}
virtual bool can_convert_varstring(const Field_varstring *field,
const Column_definition &new_type) const
{
return false;
}
virtual bool can_convert_blob(const Field_blob *field,
const Column_definition &new_type) const
{
return false;
}
virtual bool can_convert_geom(const Field_geom *field,
const Column_definition &new_type) const
virtual bool can_convert_nocopy(const Field &,
const Column_definition &) const
{
return false;
}

View file

@ -6948,7 +6948,7 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
bool is_equal= field->is_equal(*new_field);
if (!is_equal)
{
if (field->can_be_converted_by_engine(*new_field))
if (field->table->file->can_convert_nocopy(*field, *new_field))
{
/*
New column type differs from the old one, but storage engine can

View file

@ -21159,6 +21159,26 @@ bool ha_innobase::can_convert_blob(const Field_blob *field,
return true;
}
bool ha_innobase::can_convert_nocopy(const Field &field,
const Column_definition &new_type) const
{
if (const Field_string *tf= dynamic_cast<const Field_string *>(&field))
return can_convert_string(tf, new_type);
if (const Field_varstring *tf= dynamic_cast<const Field_varstring *>(&field))
return can_convert_varstring(tf, new_type);
if (dynamic_cast<const Field_geom *>(&field))
return false;
if (const Field_blob *tf= dynamic_cast<const Field_blob *>(&field))
return can_convert_blob(tf, new_type);
return false;
}
Compare_keys ha_innobase::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
@ -21169,7 +21189,7 @@ Compare_keys ha_innobase::compare_key_parts(
if (!is_equal)
{
if (!old_field.can_be_converted_by_engine(new_field))
if (!old_field.table->file->can_convert_nocopy(old_field, new_field))
return Compare_keys::NotEqual;
if (!Charset(old_cs).eq_collation_specific_names(new_cs))

View file

@ -419,15 +419,9 @@ public:
@retval false if pushed (always) */
bool rowid_filter_push(Rowid_filter *rowid_filter) override;
bool
can_convert_string(const Field_string* field,
const Column_definition& new_field) const override;
bool can_convert_varstring(
const Field_varstring* field,
const Column_definition& new_field) const override;
bool
can_convert_blob(const Field_blob* field,
const Column_definition& new_field) const override;
bool can_convert_nocopy(const Field &field,
const Column_definition& new_field) const
override;
/** @return whether innodb_strict_mode is active */
static bool is_innodb_strict_mode(THD* thd);
@ -442,6 +436,16 @@ public:
const KEY_PART_INFO& new_part) const override;
protected:
bool
can_convert_string(const Field_string* field,
const Column_definition& new_field) const;
bool can_convert_varstring(
const Field_varstring* field,
const Column_definition& new_field) const;
bool
can_convert_blob(const Field_blob* field,
const Column_definition& new_field) const;
dberr_t innobase_get_autoinc(ulonglong* value);
dberr_t innobase_lock_autoinc();
ulonglong innobase_peek_autoinc();