Commit 0ae3ea79 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-15563: Instant VARCHAR extension for ROW_FORMAT=REDUNDANT

In the original InnoDB storage format (which was retroactively named
ROW_FORMAT=REDUNDANT in MySQL 5.0.3), the length of each index field
is stored explicitly. Thus, we can and from now on will allow arbitrary
extension of VARBINARY and VARCHAR columns when the table is in
ROW_FORMAT=REDUNDANT.

ha_innobase::open(): Advertise a new HA_EXTENDED_TYPES_CONVERSION
capability for ROW_FORMAT=REDUNDANT tables.

Field_varstring::is_equal(): If the HA_EXTENDED_TYPES_CONVERSION
capability is advertised for the table, return IS_EQUAL_PACK_LENGTH
for any length extension.
parent ad17875c
......@@ -439,6 +439,23 @@ t1 CREATE TABLE `t1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL,
f2 VARCHAR(128),
INDEX idx(f2(40)))ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
CALL get_table_id("test/t1", @tbl_id);
ALTER TABLE t1 MODIFY f2 VARCHAR(300);
CALL get_table_id("test/t1", @tbl1_id);
SELECT @tbl1_id = @tbl_id;
@tbl1_id = @tbl_id
1
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`f1` int(11) NOT NULL,
`f2` varchar(300) DEFAULT NULL,
KEY `idx` (`f2`(40))
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL,
f2 VARCHAR(100),
INDEX idx(f2(40)))ENGINE=InnoDB;
CALL get_table_id("test/t1", @tbl_id);
......
......@@ -318,6 +318,18 @@ SELECT @tbl1_id = @tbl_id;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL,
f2 VARCHAR(128),
INDEX idx(f2(40)))ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
CALL get_table_id("test/t1", @tbl_id);
ALTER TABLE t1 MODIFY f2 VARCHAR(300);
CALL get_table_id("test/t1", @tbl1_id);
SELECT @tbl1_id = @tbl_id;
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1(f1 INT NOT NULL,
f2 VARCHAR(100),
INDEX idx(f2(40)))ENGINE=InnoDB;
......
/*
Copyright (c) 2000, 2017, Oracle and/or its affiliates.
Copyright (c) 2008, 2017, MariaDB
Copyright (c) 2008, 2019, 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
......@@ -7912,7 +7912,8 @@ uint Field_varstring::is_equal(Create_field *new_field)
return IS_EQUAL_YES;
if (field_length <= 127 ||
new_field->length <= 255 ||
field_length > 255)
field_length > 255 ||
(table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION))
return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length
}
......
......@@ -2,7 +2,7 @@
#define HANDLER_INCLUDED
/*
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2009, 2018, MariaDB
Copyright (c) 2009, 2019, MariaDB
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
......@@ -319,6 +319,11 @@ enum enum_alter_inplace_result {
/* Safe for online backup */
#define HA_CAN_ONLINE_BACKUPS (1ULL << 56)
/** whether every data field explicitly stores length
(holds for InnoDB ROW_FORMAT=REDUNDANT) */
#define HA_EXTENDED_TYPES_CONVERSION (1ULL << 57)
#define HA_LAST_TABLE_FLAG HA_EXTENDED_TYPES_CONVERSION
/* bits in index_flags(index_number) for what you can do with index */
#define HA_READ_NEXT 1 /* TODO really use this flag */
#define HA_READ_PREV 2 /* supports ::index_prev */
......@@ -3141,7 +3146,11 @@ class handler :public Sql_alloc
/**
The cached_table_flags is set at ha_open and ha_external_lock
*/
Table_flags ha_table_flags() const { return cached_table_flags; }
Table_flags ha_table_flags() const
{
DBUG_ASSERT(cached_table_flags < (HA_LAST_TABLE_FLAG << 1));
return cached_table_flags;
}
/**
These functions represent the public interface to *users* of the
handler class, hence they are *not* virtual. For the inheritance
......
......@@ -6121,6 +6121,11 @@ ha_innobase::open(const char* name, int, uint)
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
if (!ib_table->not_redundant()) {
m_int_table_flags |= HA_EXTENDED_TYPES_CONVERSION;
cached_table_flags |= HA_EXTENDED_TYPES_CONVERSION;
}
size_t n_fields = omits_virtual_cols(*table_share)
? table_share->stored_fields : table_share->fields;
size_t n_cols = dict_table_get_n_user_cols(ib_table)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment