MDEV-18627 Wrong result after instant size change of integer

If we instantly change the size of a fixed-length field
and treat it as kind-of variable-length, then we will need
conversions between old column values and new ones.

I tried adding such a conversion to row_build(), but then I
noticed that more conversions would be needed, because
old values still appeared in a freshly rebuilt secondary index,
causing a mismatch when trying to search with the correct
longer value that was converted in my provisional fix to row_build().

So, we will revert the essential part of
MDEV-15563: Instant ROW_FORMAT=REDUNDANT column extension
(commit 22feb179ae166500ec91feec6246c8154e33f9a2), but not
remove any tests.
This commit is contained in:
Marko Mäkelä 2019-02-18 18:30:01 +02:00
parent f0b65102b2
commit 2c74799d64
20 changed files with 186 additions and 246 deletions

View File

@ -741,8 +741,8 @@ CREATE TABLE t1 (f TINYINT, g SMALLINT UNSIGNED) ENGINE=InnoDB ROW_FORMAT=REDUND
INSERT INTO t1 VALUES(127,6502),(-128,33101);
ALTER TABLE t1 MODIFY f SMALLINT DEFAULT 12345,
MODIFY g BIGINT UNSIGNED DEFAULT 1234567;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
affected rows: 2
info: Records: 2 Duplicates: 0 Warnings: 0
SELECT * FROM t1;
f g
127 6502
@ -803,8 +803,8 @@ info: Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE t1 MODIFY f MEDIUMINT NOT NULL DEFAULT 64802,
MODIFY c VARCHAR(20) NOT NULL DEFAULT 'gory',
ADD d DATETIME;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
affected rows: 1
info: Records: 1 Duplicates: 0 Warnings: 0
INSERT INTO t1() VALUES();
INSERT INTO t1 (c,f,d) VALUES ('fury', -8388608, now());
SELECT * FROM t1;
@ -818,23 +818,25 @@ SELECT table_id INTO @table_id1 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t1';
INSERT INTO t1 VALUES (-42, -123456);
ALTER TABLE t1 CHANGE t s SMALLINT;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
affected rows: 1
info: Records: 1 Duplicates: 0 Warnings: 0
SELECT table_id INTO @table_id2 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t1';
affected rows: 1
ALTER TABLE t1 CHANGE m i INT, ALGORITHM=INSTANT;
ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY
ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY
ALTER TABLE t1 CHANGE m i INT;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
affected rows: 1
info: Records: 1 Duplicates: 0 Warnings: 0
SELECT table_id INTO @table_id3 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS
WHERE name = 'test/t1';
affected rows: 1
SELECT @table_id1 = @table_id2, @table_id2 = @table_id3;
@table_id1 = @table_id2 @table_id2 = @table_id3
0 1
0 0
INSERT IGNORE INTO t1 VALUES (0, -123456);
Warnings:
Warning 1062 Duplicate entry '-123456' for key 'm'
REPLACE INTO t1 VALUES(-42, 123456);
INSERT IGNORE INTO t1 VALUES(32768, 2147483648);
Warnings:
@ -842,11 +844,25 @@ Warning 1264 Out of range value for column 's' at row 1
Warning 1264 Out of range value for column 'i' at row 1
SELECT * FROM t1;
s i
-42 -123456
0 -123456
-42 123456
32767 2147483647
DROP TABLE t1;
CREATE TABLE t1 (a SERIAL, b INT, c TINYINT UNIQUE) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
INSERT INTO t1 (c) VALUES(1),(2),(3);
ALTER TABLE t1 MODIFY c BIGINT;
affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
UPDATE t1 SET b=1 WHERE c=2;
UPDATE t1 SET c=4 WHERE a=3;
UPDATE t1 SET b=2 WHERE c>3;
UPDATE t1 SET c=c+1;
ERROR 23000: Duplicate entry '2' for key 'c'
SELECT * FROM t1;
a b c
1 NULL 1
2 1 2
3 2 4
DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@ -1640,6 +1656,22 @@ s i
-42 123456
32767 2147483647
DROP TABLE t1;
CREATE TABLE t1 (a SERIAL, b INT, c TINYINT UNIQUE) ENGINE=InnoDB ROW_FORMAT=COMPACT;
INSERT INTO t1 (c) VALUES(1),(2),(3);
ALTER TABLE t1 MODIFY c BIGINT;
affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
UPDATE t1 SET b=1 WHERE c=2;
UPDATE t1 SET c=4 WHERE a=3;
UPDATE t1 SET b=2 WHERE c>3;
UPDATE t1 SET c=c+1;
ERROR 23000: Duplicate entry '2' for key 'c'
SELECT * FROM t1;
a b c
1 NULL 1
2 1 2
3 2 4
DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@ -2433,10 +2465,26 @@ s i
-42 123456
32767 2147483647
DROP TABLE t1;
CREATE TABLE t1 (a SERIAL, b INT, c TINYINT UNIQUE) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t1 (c) VALUES(1),(2),(3);
ALTER TABLE t1 MODIFY c BIGINT;
affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
UPDATE t1 SET b=1 WHERE c=2;
UPDATE t1 SET c=4 WHERE a=3;
UPDATE t1 SET b=2 WHERE c>3;
UPDATE t1 SET c=c+1;
ERROR 23000: Duplicate entry '2' for key 'c'
SELECT * FROM t1;
a b c
1 NULL 1
2 1 2
3 2 4
DROP TABLE t1;
disconnect analyze;
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
instants
175
174
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;

View File

@ -1,23 +1,5 @@
--- instant_alter_charset.result
+++ instant_alter_charset,redundant.result
@@ -143,7 +143,7 @@
drop index ab,
add unique key ab(a,c),
algorithm=instant;
-ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY
+ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY
drop table key_part_change;
create table key_part_change_and_rename (
a char(100) charset ascii,
@@ -156,7 +156,7 @@
drop index ab,
add unique key ab(a,b),
algorithm=instant;
-ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY
+ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY
drop table key_part_change_and_rename;
create table enum_and_set (
a enum('one', 'two') charset utf8mb3,
@@ -254,7 +254,6 @@
alter table boundary_255
modify b varchar(200) charset utf8mb3,

View File

@ -715,6 +715,19 @@ INSERT IGNORE INTO t1 VALUES(32768, 2147483648);
SELECT * FROM t1;
DROP TABLE t1;
eval CREATE TABLE t1 (a SERIAL, b INT, c TINYINT UNIQUE) $engine;
INSERT INTO t1 (c) VALUES(1),(2),(3);
--enable_info
ALTER TABLE t1 MODIFY c BIGINT;
--disable_info
UPDATE t1 SET b=1 WHERE c=2;
UPDATE t1 SET c=4 WHERE a=3;
UPDATE t1 SET b=2 WHERE c>3;
--error ER_DUP_ENTRY
UPDATE t1 SET c=c+1;
SELECT * FROM t1;
DROP TABLE t1;
dec $format;
}
disconnect analyze;

View File

@ -1,8 +1,10 @@
--source include/have_innodb.inc
--source include/innodb_row_format.inc
--source include/maybe_debug.inc
-- echo #
-- echo # MDEV-15563: Instant ROW_FORMAT=REDUNDANT column type change&extension
-- echo # (reverted in MDEV-18627)
-- echo #
# Use character-set-server in test db
@ -10,8 +12,6 @@ create or replace database test;
use test;
set default_storage_engine=innodb;
set @save_format= @@GLOBAL.innodb_default_row_format;
SET GLOBAL innodb_default_row_format=redundant;
set @bigval= repeat('0123456789', 30);
delimiter ~~;
@ -45,7 +45,9 @@ set @save_debug= @@SESSION.debug_dbug;
set debug_dbug= '+d,ib_instant_error';
--enable_query_log
}
alter table t modify a char(200), algorithm=instant;
--enable_info
alter table t modify a char(200);
--disable_info
select count(a) from t where a = @bigval;
select a, length(a) from t where a = 'z';
@ -53,7 +55,9 @@ check table t extended;
call check_table('t');
--echo # CHAR enlargement
alter table t modify a char(220), algorithm=instant;
--enable_info
alter table t modify a char(220);
--disable_info
select count(a) from t where a = @bigval;
select a, length(a) from t where a = 'z';
@ -61,10 +65,10 @@ check table t extended;
call check_table('t');
--echo # Convert from VARCHAR to a bigger CHAR
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
alter table t modify a varchar(200), algorithm=instant;
alter table t modify a varchar(200), algorithm=copy;
alter table t modify a char(255), algorithm=instant;
--enable_info
alter table t modify a varchar(200);
alter table t modify a char(255);
--disable_info
select count(a) from t where a = @bigval;
select a, length(a) from t where a = 'z';
@ -74,14 +78,17 @@ call check_table('t');
--echo # BINARY/VARBINARY test
create or replace table t (a varbinary(300));
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
alter table t modify a binary(255), algorithm=instant;
alter table t modify a binary(255), algorithm=copy;
insert into t values(NULL);
--enable_info
alter table t modify a binary(255);
--disable_info
create or replace table t (a varbinary(200));
insert into t values (@bigval);
insert into t values ('z');
alter table t modify a binary(200), algorithm=instant;
--enable_info
alter table t modify a binary(200);
--disable_info
select count(a) from t where a = @bigval;
select length(a) from t where left(a, 1) = 'z';
@ -89,16 +96,18 @@ check table t extended;
call check_table('t');
--echo # BINARY enlargement
alter table t modify a binary(220), algorithm=instant;
--enable_info
alter table t modify a binary(220);
--disable_info
check table t extended;
call check_table('t');
--echo # Convert from VARBINARY to a bigger BINARY
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
alter table t modify a varbinary(220), algorithm=instant;
alter table t modify a varbinary(220), algorithm=copy;
alter table t modify a binary(255), algorithm=instant;
--enable_info
alter table t modify a varbinary(220);
alter table t modify a binary(255);
--disable_info
select count(a) from t where a = @bigval;
select a, length(a) from t where a = 'z';
@ -110,25 +119,33 @@ call check_table('t');
--echo # Integer conversions
create or replace table t (x tinyint);
insert into t values (127);
alter table t modify x smallint, algorithm=instant;
--enable_info
alter table t modify x smallint;
--disable_info
select * from t;
check table t extended;
call check_table('t');
update t set x= 32767;
alter table t modify x mediumint, algorithm=instant;
--enable_info
alter table t modify x mediumint;
--disable_info
select * from t;
check table t extended;
call check_table('t');
update t set x= 8388607;
alter table t modify x int, algorithm=instant;
--enable_info
alter table t modify x int;
--disable_info
select * from t;
check table t extended;
call check_table('t');
update t set x= 2147483647;
alter table t modify x bigint, algorithm=instant;
--enable_info
alter table t modify x bigint;
--disable_info
select * from t;
check table t extended;
call check_table('t');
@ -163,13 +180,19 @@ call check_table('t2');
create or replace table t1 (x mediumint);
insert into t1 values (1);
insert into t1 values (1);
alter table t1 add column y int first, modify x int, algorithm instant;
--enable_info
alter table t1 add column y int first, modify x int;
--error ER_DUP_ENTRY
alter table t1 add column z int first, add primary key (x);
--disable_info
--echo # Check assertion in wrong instant operation
create or replace table t1 (a varchar(26) not null) default character set utf8mb4;
alter table t1 modify a varchar(25) not null;
insert into t1 values ('abcdef'), (repeat('x',26));
--enable_info
alter ignore table t1 modify a varchar(25) not null;
--disable_info
select * from t1;
--echo # Check row_mysql_store_col_in_innobase_format()
create or replace table t1(x int primary key, a varchar(20));
@ -181,30 +204,46 @@ update t1 set a= 'foo' where x = 2;
--echo #
create or replace table t1 (x int, y int);
insert into t1 (x, y) values (11, 22);
alter table t1 modify x bigint, algorithm instant;
alter table t1 add primary key (x), algorithm inplace;
--enable_info
alter table t1 modify x bigint;
alter table t1 add primary key (x);
--disable_info
select * from t1;
check table t1;
create or replace table t1 (a varchar(10), y int);
insert into t1 (a, y) values ("0123456789", 33);
alter table t1 modify a char(15), algorithm instant;
alter table t1 add primary key (a), algorithm inplace;
--enable_info
alter table t1 modify a char(15);
alter table t1 add primary key (a);
--disable_info
select * from t1;
check table t1;
create or replace table t1 (x int primary key, y int);
insert into t1 (x, y) values (44, 55);
alter table t1 modify x bigint, algorithm inplace;
--enable_info
alter table t1 modify x bigint;
--disable_info
select * from t1;
check table t1;
create or replace table t1 (x int primary key, y int);
insert into t1 values (66, 77);
alter table t1 add column z int, algorithm instant;
alter table t1 drop column y, algorithm instant;
--enable_info
alter table t1 add column z int;
alter table t1 drop column y;
--disable_info
select * from t1;
check table t1;
create or replace table t1 (x integer, a varchar(20));
alter table t1 add index idx3 (a);
--enable_info
insert into t1 (x, a) values (73, 'a');
alter table t1 add index idx3 (a);
alter table t1 modify a char(20);
--disable_info
select * from t1;
check table t1;
create or replace database test charset latin1;
SET GLOBAL innodb_default_row_format=@save_format;

View File

@ -7084,9 +7084,6 @@ uint Field_str::is_equal(Create_field *new_field)
return new_field->charset == field_charset
? IS_EQUAL_YES : IS_EQUAL_PACK_LENGTH;
if (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)
return IS_EQUAL_PACK_LENGTH_EXT;
return IS_EQUAL_NO;
}
@ -7947,11 +7944,6 @@ uint Field_varstring::is_equal(Create_field *new_field)
(table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION))
return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length
}
else if (new_type_handler == &type_handler_string) // converting to CHAR
{
if (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)
return IS_EQUAL_PACK_LENGTH_EXT;
}
return IS_EQUAL_NO;
}
@ -9568,22 +9560,6 @@ uint Field_num::is_equal(Create_field *new_field)
format for integers, we can only return IS_EQUAL_YES for the TINYINT
conversion. */
if (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)
{
/* For now, prohibit instant conversion between BIT and integers.
Note: pack_length(), which is compared below, is measured in
bytes, and for BIT the last byte may be partially occupied. We
must not allow instant conversion to BIT such that the last byte
is partially occupied.
We could allow converting TINYINT UNSIGNED to BIT(8) or wider. */
if (th != new_th &&
(th == &type_handler_bit || new_th == &type_handler_bit))
return IS_EQUAL_NO;
if (th->result_type() == new_th->result_type() &&
new_field->pack_length >= pack_length())
return IS_EQUAL_PACK_LENGTH_EXT;
}
return IS_EQUAL_NO;
}

View File

@ -751,14 +751,6 @@ typedef ulonglong alter_table_operations;
*/
#define ALTER_COLUMN_INDEX_LENGTH (1ULL << 60)
/**
Change the column length or type such that no rebuild is needed.
Only set if ALTER_COLUMN_EQUAL_PACK_LENGTH does not apply, and
if HA_EXTENDED_TYPES_CONVERSION holds.
@see IS_EQUAL_PACK_LENGTH_EXT
*/
#define ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT (1ULL << 61)
/*
Flags set in partition_flags when altering partitions
*/

View File

@ -358,11 +358,6 @@
data dictionary without changing table rows
*/
#define IS_EQUAL_PACK_LENGTH 2
/**
new_field has a representation that is compatible with the old type
when the storage engine advertises HA_EXTENDED_TYPES_CONVERSION
*/
#define IS_EQUAL_PACK_LENGTH_EXT 3
enum enum_parsing_place
{

View File

@ -6605,9 +6605,6 @@ static bool fill_alter_inplace_info(THD *thd,
*/
ha_alter_info->handler_flags|= ALTER_COLUMN_EQUAL_PACK_LENGTH;
break;
case IS_EQUAL_PACK_LENGTH_EXT:
ha_alter_info->handler_flags|= ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT;
break;
default:
DBUG_ASSERT(0);
/* Safety. */

View File

@ -4839,9 +4839,7 @@ n_field_mismatch:
if (len_is_stored(len)
&& (field->prefix_len
? len > field->prefix_len
: (fixed_size && (page_is_comp(page)
? len != fixed_size
: len > fixed_size)))) {
: (fixed_size && len != fixed_size))) {
len_mismatch:
btr_index_rec_validate_report(page, rec, index);
ib::error error;

View File

@ -486,14 +486,8 @@ incompatible:
For the metadata record, variable-length columns are
always written with zero length. The DB_TRX_ID will
start right after any fixed-length columns. */
if (index->table->not_redundant()) {
for (uint i = index->n_uniq; i--; ) {
trx_id_offset += index->fields[i]
.fixed_len;
}
} else {
trx_id_offset = rec_get_field_start_offs(
rec, index->n_uniq);
for (uint i = index->n_uniq; i--; ) {
trx_id_offset += index->fields[i].fixed_len;
}
}

View File

@ -100,22 +100,6 @@ dtype_validate(
return(TRUE);
}
bool dict_col_t::same_charset(const dict_col_t& other) const
{
if (dtype_is_non_binary_string_type(mtype, prtype)
&& dtype_is_non_binary_string_type(other.mtype, other.prtype)) {
uint csn1 = (uint) dtype_get_charset_coll(prtype);
uint csn2 = (uint) dtype_get_charset_coll(other.prtype);
CHARSET_INFO* cs1 = get_charset(csn1, MYF(MY_WME));
CHARSET_INFO* cs2 = get_charset(csn2, MYF(MY_WME));
if (!my_charset_same(cs1, cs2)) {
return false;
}
}
return true;
}
#ifdef UNIV_DEBUG
/** Print a data type structure.
@param[in] type data type */

View File

@ -2203,14 +2203,6 @@ dict_index_too_big_for_tree(
}
field_max_size = dict_col_get_max_size(col);
if (!comp && (col->mtype == DATA_INT
|| col->mtype == DATA_CHAR
|| col->mtype == DATA_FIXBINARY)) {
/* DATA_INT, DATA_FIXBINARY and DATA_CHAR are variable-
length (enlarged instantly), but are stored locally. */
field_ext_max_size = 0;
goto add_field_size;
}
field_ext_max_size = field_max_size < 256 ? 1 : 2;
if (field->prefix_len) {

View File

@ -9977,7 +9977,7 @@ innobase_fts_create_doc_id_key(
/* The unique Doc ID field should be an eight-bytes integer */
dict_field_t* field = dict_index_get_nth_field(index, 0);
ut_a(field->col->mtype == DATA_INT);
ut_ad(sizeof(*doc_id) == field->col->len);
ut_ad(sizeof(*doc_id) == field->fixed_len);
ut_ad(!strcmp(index->name, FTS_DOC_ID_INDEX_NAME));
#endif /* UNIV_DEBUG */

View File

@ -135,7 +135,6 @@ static const alter_table_operations INNOBASE_ALTER_INSTANT
| ALTER_ADD_VIRTUAL_COLUMN
| INNOBASE_FOREIGN_OPERATIONS
| ALTER_COLUMN_EQUAL_PACK_LENGTH
| ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT
| ALTER_COLUMN_UNVERSIONED
| ALTER_DROP_VIRTUAL_COLUMN;
@ -270,7 +269,7 @@ inline void dict_table_t::prepare_instant(const dict_table_t& old,
ut_ad(!not_redundant());
for (unsigned i = index.n_fields; i--; ) {
ut_ad(index.fields[i].col->same_format(
*oindex.fields[i].col, true));
*oindex.fields[i].col));
}
}
#endif
@ -458,13 +457,9 @@ inline void dict_index_t::instant_add_field(const dict_index_t& instant)
as this index. Fields for any added columns are appended at the end. */
#ifndef DBUG_OFF
for (unsigned i = 0; i < n_fields; i++) {
DBUG_ASSERT(fields[i].prefix_len
== instant.fields[i].prefix_len);
DBUG_ASSERT(fields[i].fixed_len
== instant.fields[i].fixed_len
|| !table->not_redundant());
DBUG_ASSERT(instant.fields[i].col->same_format(
*fields[i].col, !table->not_redundant()));
DBUG_ASSERT(fields[i].same(instant.fields[i]));
DBUG_ASSERT(instant.fields[i].col->same_format(*fields[i]
.col));
/* Instant conversion from NULL to NOT NULL is not allowed. */
DBUG_ASSERT(!fields[i].col->is_nullable()
|| instant.fields[i].col->is_nullable());
@ -540,7 +535,10 @@ inline bool dict_table_t::instant_column(const dict_table_t& table,
if (const dict_col_t* o = find(old_cols, col_map, n_cols, i)) {
c.def_val = o->def_val;
ut_ad(c.same_format(*o, !not_redundant()));
DBUG_ASSERT(!((c.prtype ^ o->prtype)
& ~(DATA_NOT_NULL | DATA_VERSIONED)));
DBUG_ASSERT(c.mtype == o->mtype);
DBUG_ASSERT(c.len >= o->len);
if (o->vers_sys_start()) {
ut_ad(o->ind == vers_start);
@ -1752,10 +1750,6 @@ ha_innobase::check_if_supported_inplace_alter(
{
DBUG_ENTER("check_if_supported_inplace_alter");
DBUG_ASSERT(!(ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT
& ha_alter_info->handler_flags)
|| !m_prebuilt->table->not_redundant());
if ((ha_alter_info->handler_flags
& INNOBASE_ALTER_VERSIONED_REBUILD)
&& altered_table->versioned(VERS_TIMESTAMP)) {
@ -2951,7 +2945,7 @@ innobase_col_to_mysql(
switch (col->mtype) {
case DATA_INT:
ut_ad(len <= flen);
ut_ad(len == flen);
/* Convert integer data from Innobase to little-endian
format, sign bit restored to normal */
@ -5592,8 +5586,7 @@ static bool innobase_instant_try(
bool update = old && (!ctx->first_alter_pos
|| i < ctx->first_alter_pos - 1);
ut_ad(!old || col->same_format(
*old, !user_table->not_redundant()));
DBUG_ASSERT(!old || col->same_format(*old));
if (update
&& old->prtype == d->type.prtype) {
/* The record is already present in SYS_COLUMNS. */
@ -5682,8 +5675,6 @@ add_all_virtual:
NULL, trx, ctx->heap, NULL);
dberr_t err = DB_SUCCESS;
DBUG_EXECUTE_IF("ib_instant_error",
err = DB_OUT_OF_FILE_SPACE; goto func_exit;);
if (rec_is_metadata(rec, *index)) {
ut_ad(page_rec_is_user_rec(rec));
if (!page_has_next(block->frame)
@ -9061,7 +9052,7 @@ innobase_rename_or_enlarge_column_try(
and ROW_FORMAT is not REDUNDANT and mbminlen<mbmaxlen.
That is, we treat a UTF-8 CHAR(n) column somewhat like
a VARCHAR. */
ut_ad(!user_table->not_redundant() || col->len == len);
ut_ad(col->len == len);
break;
case DATA_BINARY:
case DATA_VARCHAR:
@ -9069,11 +9060,6 @@ innobase_rename_or_enlarge_column_try(
case DATA_DECIMAL:
case DATA_BLOB:
break;
case DATA_INT:
if (!user_table->not_redundant()) {
break;
}
/* fall through */
default:
ut_ad(col->prtype == prtype);
ut_ad(col->mtype == mtype);
@ -9129,7 +9115,6 @@ innobase_rename_or_enlarge_columns_try(
if (!(ha_alter_info->handler_flags
& (ALTER_COLUMN_EQUAL_PACK_LENGTH
| ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT
| ALTER_COLUMN_NAME))) {
DBUG_RETURN(false);
}
@ -9178,7 +9163,6 @@ innobase_rename_or_enlarge_columns_cache(
{
if (!(ha_alter_info->handler_flags
& (ALTER_COLUMN_EQUAL_PACK_LENGTH
| ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT
| ALTER_COLUMN_NAME))) {
return;
}

View File

@ -472,18 +472,12 @@ dtype_get_fixed_size_low(
}
#endif /* UNIV_DEBUG */
/* fall through */
case DATA_CHAR:
case DATA_FIXBINARY:
case DATA_INT:
case DATA_FLOAT:
case DATA_DOUBLE:
return(len);
case DATA_FIXBINARY:
case DATA_CHAR:
case DATA_INT:
/* Treat these types as variable length for redundant
row format. We can't rely on fixed_len anymore because record
can have shorter length from before instant enlargement
[MDEV-15563]. Note, that importing such tablespace to
earlier MariaDB versions produces ER_TABLE_SCHEMA_MISMATCH. */
return comp ? len : 0;
case DATA_MYSQL:
if (prtype & DATA_BINARY_TYPE) {
return(len);
@ -631,14 +625,6 @@ dtype_get_sql_null_size(
const dtype_t* type, /*!< in: type */
ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */
{
switch (type->mtype) {
case DATA_INT:
case DATA_CHAR:
case DATA_FIXBINARY:
return(type->len);
default:
break;
}
return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len,
type->mbminlen, type->mbmaxlen, comp));
}

View File

@ -682,52 +682,18 @@ public:
def_val.data = NULL;
}
private:
/** Determine if the columns have the same character set
@param[in] other column to compare to
@return whether the columns have the same character set */
bool same_charset(const dict_col_t& other) const;
public:
/** Determine if the columns have the same format
except for is_nullable() and is_versioned().
@param[in] other column to compare to
@param[in] redundant table is redundant row format
@return whether the columns have the same format */
bool same_format(const dict_col_t& other, bool redundant = false) const
bool same_format(const dict_col_t& other) const
{
if (len < other.len
|| mbminlen != other.mbminlen
|| mbmaxlen != other.mbmaxlen) {
return false;
}
if (!((prtype ^ other.prtype)
& ~(DATA_NOT_NULL | DATA_VERSIONED))) {
return mtype == other.mtype;
}
if (redundant) {
switch (other.mtype) {
case DATA_CHAR:
case DATA_MYSQL:
case DATA_VARCHAR:
case DATA_VARMYSQL:
return (mtype == DATA_CHAR
|| mtype == DATA_MYSQL
|| mtype == DATA_VARCHAR
|| mtype == DATA_VARMYSQL)
&& same_charset(other);
case DATA_FIXBINARY:
case DATA_BINARY:
return (mtype == DATA_FIXBINARY
|| mtype == DATA_BINARY)
&& same_charset(other);
case DATA_INT:
return mtype == DATA_INT;
}
}
return false;
return mtype == other.mtype
&& len >= other.len
&& mbminlen == other.mbminlen
&& mbmaxlen == other.mbmaxlen
&& !((prtype ^ other.prtype)
& ~(DATA_NOT_NULL | DATA_VERSIONED));
}
};

View File

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2018, MariaDB Corporation.
Copyright (c) 2014, 2019, MariaDB Corporation.
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 the Free Software
@ -706,6 +706,11 @@ row_merge_buf_add(
row_field, field, col->len,
old_table->space->zip_size(),
conv_heap);
} else {
/* Field length mismatch should not
happen when rebuilding redundant row
format table. */
ut_ad(index->table->not_redundant());
}
}
}

View File

@ -887,15 +887,10 @@ row_create_prebuilt(
== MAX_REF_PARTS););
uint temp_len = 0;
for (uint i = 0; i < temp_index->n_uniq; i++) {
const dict_field_t& f = temp_index->fields[i];
if (f.col->mtype == DATA_INT) {
ut_ad(f.col->len >= f.fixed_len);
/* dtype_get_fixed_size_low() returns 0
for ROW_FORMAT=REDUNDANT */
ut_ad(table->not_redundant()
? f.col->len == f.fixed_len
: f.fixed_len == 0);
temp_len += f.col->len;
ulint type = temp_index->fields[i].col->mtype;
if (type == DATA_INT) {
temp_len +=
temp_index->fields[i].fixed_len;
}
}
srch_key_len = std::max(srch_key_len,temp_len);

View File

@ -2723,8 +2723,6 @@ row_sel_field_store_in_mysql_format_func(
switch (templ->type) {
const byte* field_end;
case DATA_CHAR:
case DATA_FIXBINARY:
case DATA_VARCHAR:
case DATA_VARMYSQL:
case DATA_BINARY:
@ -2822,8 +2820,7 @@ row_sel_field_store_in_mysql_format_func(
ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len
|| (field_no == templ->icp_rec_field_no
&& field->prefix_len > 0)
|| templ->rec_field_is_prefix
|| !index->table->not_redundant());
|| templ->rec_field_is_prefix);
ut_ad(templ->is_virtual
|| !(field->prefix_len % templ->mbmaxlen));
@ -2845,6 +2842,8 @@ row_sel_field_store_in_mysql_format_func(
ut_ad(0);
/* fall through */
case DATA_CHAR:
case DATA_FIXBINARY:
case DATA_FLOAT:
case DATA_DOUBLE:
case DATA_DECIMAL:
@ -2859,18 +2858,13 @@ row_sel_field_store_in_mysql_format_func(
case DATA_INT:
/* Convert InnoDB big-endian integer to little-endian
format, sign bit restored to 2's complement form */
DBUG_ASSERT(templ->mysql_col_len >= len);
DBUG_ASSERT(templ->mysql_col_len == len);
byte* ptr = pad;
do *--ptr = *data++; while (ptr != dest);
byte b = templ->is_unsigned || !((pad[-1] ^= 0x80) & 0x80)
? 0 : 0xff;
if (ulint l = templ->mysql_col_len - len) {
DBUG_ASSERT(!index->table->not_redundant());
memset(pad, b, l);
if (!templ->is_unsigned) {
pad[-1] ^= 0x80;
}
break;
}
}