From 6f3612fa4d126ce614a415edf88feae013820d93 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 26 Jun 2019 06:46:55 +0400 Subject: [PATCH] MDEV-19861 Add intfastructure to have ENUM columns in INFORMATION_SCHEMA --- .../innodb_i_s/innodb_buffer_page.result | 2 +- sql/sql_i_s.h | 16 +++++- sql/sql_type.cc | 22 ++++++++ sql/sql_type.h | 52 +++++++++++++++++++ storage/innobase/handler/i_s.cc | 15 +++++- 5 files changed, 103 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb_i_s/innodb_buffer_page.result b/mysql-test/suite/innodb_i_s/innodb_buffer_page.result index 52de51be179..3190c7866cf 100644 --- a/mysql-test/suite/innodb_i_s/innodb_buffer_page.result +++ b/mysql-test/suite/innodb_i_s/innodb_buffer_page.result @@ -18,7 +18,7 @@ INNODB_BUFFER_PAGE CREATE TEMPORARY TABLE `INNODB_BUFFER_PAGE` ( `DATA_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0, `COMPRESSED_SIZE` bigint(21) unsigned NOT NULL DEFAULT 0, `PAGE_STATE` varchar(64) DEFAULT NULL, - `IO_FIX` varchar(64) DEFAULT NULL, + `IO_FIX` enum('IO_NONE','IO_READ','IO_WRITE','IO_PIN') DEFAULT NULL, `IS_OLD` varchar(3) DEFAULT NULL, `FREE_PAGE_CLOCK` bigint(21) unsigned NOT NULL DEFAULT 0 ) ENGINE=MEMORY DEFAULT CHARSET=utf8 diff --git a/sql/sql_i_s.h b/sql/sql_i_s.h index 998a5a460a6..a4c29b83826 100644 --- a/sql/sql_i_s.h +++ b/sql/sql_i_s.h @@ -60,9 +60,12 @@ class Type */ uint m_char_length; uint m_unsigned_flag; + const Typelib *m_typelib; public: - Type(const Type_handler *th, uint length, uint unsigned_flag) - :m_type_handler(th), m_char_length(length), m_unsigned_flag(unsigned_flag) + Type(const Type_handler *th, uint length, uint unsigned_flag, + const Typelib *typelib= NULL) + :m_type_handler(th), m_char_length(length), m_unsigned_flag(unsigned_flag), + m_typelib(typelib) { } const Type_handler *type_handler() const { return m_type_handler; } uint char_length() const { return m_char_length; } @@ -74,6 +77,7 @@ public: return m_char_length; } uint unsigned_flag() const { return m_unsigned_flag; } + const Typelib *typelib() const { return m_typelib; } }; } // namespace Show @@ -116,6 +120,14 @@ public: namespace Show { + +class Enum: public Type +{ +public: + Enum(const Typelib *typelib) :Type(&type_handler_enum, 0, false, typelib) { } +}; + + class Blob: public Type { public: diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 3265461ae24..eb6c3376e2e 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -2347,6 +2347,28 @@ Field *Type_handler_set::make_conversion_table_field(TABLE *table, } +Field *Type_handler_enum::make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const +{ + LEX_CSTRING name= def.name(); + const Typelib *typelib= def.typelib(); + DBUG_ASSERT(typelib); + /* + Assume I_S columns don't have non-ASCII characters in names. + If we eventually want to, Typelib::max_char_length() must be implemented. + */ + return new (table->in_use->mem_root) + Field_enum(addr.ptr(), (uint32) typelib->max_octet_length(), + addr.null_ptr(), addr.null_bit(), + Field::NONE, &name, + get_enum_pack_length(typelib->count), + typelib, system_charset_info); + +} + + /*************************************************************************/ bool Type_handler:: diff --git a/sql/sql_type.h b/sql/sql_type.h index 776422081c8..90b897ab253 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -144,6 +144,54 @@ public: }; +class Typelib: public TYPELIB +{ +public: + Typelib(uint count, const char **type_names, unsigned int *type_lengths) + { + TYPELIB::count= count; + TYPELIB::name= ""; + TYPELIB::type_names= type_names; + TYPELIB::type_lengths= type_lengths; + } + uint max_octet_length() const + { + uint max_length= 0; + for (uint i= 0; i < TYPELIB::count; i++) + { + const uint length= TYPELIB::type_lengths[i]; + set_if_bigger(max_length, length); + } + return max_length; + } +}; + + +template +class TypelibBuffer: public Typelib +{ + const char *m_type_names[sz + 1]; + unsigned int m_type_lengths[sz + 1]; +public: + TypelibBuffer(uint count, const LEX_CSTRING *values) + :Typelib(count, m_type_names, m_type_lengths) + { + DBUG_ASSERT(sz >= count); + for (uint i= 0; i < count; i++) + { + DBUG_ASSERT(values[i].str != NULL); + m_type_names[i]= values[i].str; + m_type_lengths[i]= values[i].length; + } + m_type_names[sz]= NullS; // End marker + m_type_lengths[sz]= 0; // End marker + } + TypelibBuffer(const LEX_CSTRING *values) + :TypelibBuffer(sz, values) + { } +}; + + class Native: public Binary_string { public: @@ -6474,6 +6522,10 @@ public: const Bit_addr &bit, const Column_definition_attributes *attr, uint32 flags) const; + Field *make_schema_field(TABLE *table, + const Record_addr &addr, + const ST_FIELD_INFO &def, + bool show_field) const; }; diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 7269e10bd14..06796460b67 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -3914,6 +3914,19 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_buffer_stats = STRUCT_FLD(maturity, MariaDB_PLUGIN_MATURITY_STABLE), }; + +static const LEX_CSTRING io_values[]= +{ + STRING_WITH_LEN("IO_NONE"), + STRING_WITH_LEN("IO_READ"), + STRING_WITH_LEN("IO_WRITE"), + STRING_WITH_LEN("IO_PIN") +}; + + +static TypelibBuffer<4> io_values_typelib(io_values); + + namespace Show { /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = @@ -3972,7 +3985,7 @@ static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = Column("PAGE_STATE", Varchar(64), NULLABLE), #define IDX_BUFFER_PAGE_IO_FIX 16 + I_S_AHI - Column("IO_FIX", Varchar(64), NULLABLE), + Column("IO_FIX", Enum(&io_values_typelib), NULLABLE), #define IDX_BUFFER_PAGE_IS_OLD 17 + I_S_AHI Column("IS_OLD", Varchar(3), NULLABLE),