summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/main/partition_pruning.result10
-rw-r--r--mysql-test/main/partition_pruning.test13
-rw-r--r--mysql-test/suite/innodb/r/instant_alter,4k.rdiff4
-rw-r--r--mysql-test/suite/innodb/r/instant_alter.result26
-rw-r--r--mysql-test/suite/innodb/t/instant_alter.test9
-rw-r--r--sql/ha_partition.cc5
-rw-r--r--storage/innobase/btr/btr0cur.cc53
-rw-r--r--storage/innobase/handler/handler0alter.cc8
-rw-r--r--storage/innobase/include/rem0rec.h18
-rw-r--r--storage/innobase/rem/rem0rec.cc18
10 files changed, 135 insertions, 29 deletions
diff --git a/mysql-test/main/partition_pruning.result b/mysql-test/main/partition_pruning.result
index 15767556f37..f8ae65fbcea 100644
--- a/mysql-test/main/partition_pruning.result
+++ b/mysql-test/main/partition_pruning.result
@@ -3487,6 +3487,16 @@ a b c d
1 a b 1
drop table t1;
#
+# MDEV-14667 Assertion `used_parts > 0' failed in ha_partition::init_record_priority_queue.
+#
+create table t1 (a int);
+insert into t1 values (1),(2);
+create table t2 (b int, c int, key(c,b)) partition by hash(b) partitions 2;
+insert into t2 values (3,4),(5,6);
+select straight_join * from t1, t2 where b != NULL;
+a b c
+drop table t1, t2;
+#
# MDEV-17493: Partition pruning doesn't work for nested outer joins
#
create table t0(a int);
diff --git a/mysql-test/main/partition_pruning.test b/mysql-test/main/partition_pruning.test
index aea61a941f7..d59f52be313 100644
--- a/mysql-test/main/partition_pruning.test
+++ b/mysql-test/main/partition_pruning.test
@@ -1539,6 +1539,19 @@ select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) O
drop table t1;
--echo #
+--echo # MDEV-14667 Assertion `used_parts > 0' failed in ha_partition::init_record_priority_queue.
+--echo #
+
+create table t1 (a int);
+insert into t1 values (1),(2);
+
+create table t2 (b int, c int, key(c,b)) partition by hash(b) partitions 2;
+insert into t2 values (3,4),(5,6);
+
+select straight_join * from t1, t2 where b != NULL;
+drop table t1, t2;
+
+--echo #
--echo # MDEV-17493: Partition pruning doesn't work for nested outer joins
--echo #
diff --git a/mysql-test/suite/innodb/r/instant_alter,4k.rdiff b/mysql-test/suite/innodb/r/instant_alter,4k.rdiff
index 200868cbf4e..d3a1cee8a85 100644
--- a/mysql-test/suite/innodb/r/instant_alter,4k.rdiff
+++ b/mysql-test/suite/innodb/r/instant_alter,4k.rdiff
@@ -318,8 +318,8 @@
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
instants
--184
-+186
+-187
++189
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;
#
# MDEV-18266: Changing an index comment unnecessarily rebuilds index
diff --git a/mysql-test/suite/innodb/r/instant_alter.result b/mysql-test/suite/innodb/r/instant_alter.result
index b7bc5abb81f..e03ddfb9956 100644
--- a/mysql-test/suite/innodb/r/instant_alter.result
+++ b/mysql-test/suite/innodb/r/instant_alter.result
@@ -904,6 +904,14 @@ a b c
1 a NULL
2 bah 3
DROP TABLE t1;
+CREATE TABLE t1(a CHAR(5) CHARACTER SET utf8 PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
+INSERT INTO t1 VALUES('barf');
+ALTER TABLE t1 ADD b INT FIRST, ALGORITHM=INSTANT;
+ALTER TABLE t1 ADD vb INT AS (b);
+SELECT * FROM t1;
+b a vb
+NULL barf NULL
+DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@@ -1753,6 +1761,14 @@ a b c
1 a NULL
2 bah 3
DROP TABLE t1;
+CREATE TABLE t1(a CHAR(5) CHARACTER SET utf8 PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPACT;
+INSERT INTO t1 VALUES('barf');
+ALTER TABLE t1 ADD b INT FIRST, ALGORITHM=INSTANT;
+ALTER TABLE t1 ADD vb INT AS (b);
+SELECT * FROM t1;
+b a vb
+NULL barf NULL
+DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@@ -2602,12 +2618,20 @@ a b c
1 a NULL
2 bah 3
DROP TABLE t1;
+CREATE TABLE t1(a CHAR(5) CHARACTER SET utf8 PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+INSERT INTO t1 VALUES('barf');
+ALTER TABLE t1 ADD b INT FIRST, ALGORITHM=INSTANT;
+ALTER TABLE t1 ADD vb INT AS (b);
+SELECT * FROM t1;
+b a vb
+NULL barf NULL
+DROP TABLE t1;
disconnect analyze;
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
instants
-184
+187
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;
#
# MDEV-18266: Changing an index comment unnecessarily rebuilds index
diff --git a/mysql-test/suite/innodb/t/instant_alter.test b/mysql-test/suite/innodb/t/instant_alter.test
index 8fc8fe6cd6d..c48a9e45fdc 100644
--- a/mysql-test/suite/innodb/t/instant_alter.test
+++ b/mysql-test/suite/innodb/t/instant_alter.test
@@ -790,6 +790,15 @@ INSERT INTO t1 VALUES(2,'bah',3);
SELECT * FROM t1;
DROP TABLE t1;
+# MDEV-21088 Table cannot be loaded after instant ADD/DROP COLUMN
+eval CREATE TABLE t1(a CHAR(5) CHARACTER SET utf8 PRIMARY KEY) $engine;
+INSERT INTO t1 VALUES('barf');
+ALTER TABLE t1 ADD b INT FIRST, ALGORITHM=INSTANT;
+# this evicts and reloads the table definition until MDEV-17468 is fixed
+ALTER TABLE t1 ADD vb INT AS (b);
+SELECT * FROM t1;
+DROP TABLE t1;
+
dec $format;
let $redundant_4k= 0;
}
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 005f8e98868..e4ab4cb68f5 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -5266,7 +5266,10 @@ bool ha_partition::init_record_priority_queue()
{
size_t alloc_len;
uint used_parts= bitmap_bits_set(&m_part_info->read_partitions);
- DBUG_ASSERT(used_parts > 0);
+
+ if (used_parts == 0) /* Do nothing since no records expected. */
+ DBUG_RETURN(false);
+
/* Allocate record buffer for each used partition. */
m_priority_queue_rec_len= m_rec_length + PARTITION_BYTES_IN_POS;
if (!m_using_extended_keys)
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 0d256f7f2cb..535620db0f2 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -483,14 +483,55 @@ incompatible:
/* This metadata record includes a BLOB that identifies
any dropped or reordered columns. */
ulint trx_id_offset = index->trx_id_offset;
- if (!trx_id_offset) {
- /* The PRIMARY KEY contains variable-length columns.
- 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->trx_id_offset, the PRIMARY KEY contains
+ variable-length columns. For the metadata record,
+ variable-length columns should be written with zero
+ length. However, before MDEV-21088 was fixed, for
+ variable-length encoded PRIMARY KEY column of type
+ CHAR, we wrote more than zero bytes. That is why we
+ must determine the actual length of each PRIMARY KEY
+ column. The DB_TRX_ID will start right after any
+ PRIMARY KEY columns. */
+ ut_ad(index->n_uniq);
+
+ /* We cannot invoke rec_get_offsets() before
+ index->table->deserialise_columns(). Therefore,
+ we must duplicate some logic here. */
+ if (trx_id_offset) {
+ } else if (index->table->not_redundant()) {
+ /* PRIMARY KEY columns can never be NULL.
+ We can skip the null flag bitmap. */
+ const byte* lens = rec - (REC_N_NEW_EXTRA_BYTES + 1)
+ - index->n_core_null_bytes;
+ unsigned n_add = rec_get_n_add_field(lens);
+ ut_ad(index->n_core_fields + n_add >= index->n_fields);
+ lens -= n_add;
+
for (uint i = index->n_uniq; i--; ) {
- trx_id_offset += index->fields[i].fixed_len;
+ const dict_field_t& f = index->fields[i];
+ unsigned len = f.fixed_len;
+ if (!len) {
+ len = *lens--;
+ if ((len & 0x80)
+ && DATA_BIG_COL(f.col)) {
+ /* 1exxxxxxx xxxxxxxx */
+ len &= 0x3f;
+ len <<= 8;
+ len |= *lens--;
+ }
+ }
+ trx_id_offset += len;
}
+ } else if (rec_get_1byte_offs_flag(rec)) {
+ trx_id_offset = rec_1_get_field_end_info(
+ rec, index->n_uniq - 1);
+ ut_ad(!(trx_id_offset & REC_1BYTE_SQL_NULL_MASK));
+ trx_id_offset &= ~REC_1BYTE_SQL_NULL_MASK;
+ } else {
+ trx_id_offset = rec_2_get_field_end_info(
+ rec, index->n_uniq - 1);
+ ut_ad(!(trx_id_offset & REC_2BYTE_SQL_NULL_MASK));
+ trx_id_offset &= ~REC_2BYTE_SQL_NULL_MASK;
}
const byte* ptr = rec + trx_id_offset
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 4f58aecd101..dbeb4ce9e60 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -5636,10 +5636,17 @@ static bool innobase_instant_try(
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_LONG_BLOB:
+ variable_length:
/* Store the empty string for 'core'
variable-length NOT NULL columns. */
dfield_set_data(d, field_ref_zero, 0);
break;
+ case MYSQL_TYPE_STRING:
+ if (col->mbminlen != col->mbmaxlen
+ && user_table->not_redundant()) {
+ goto variable_length;
+ }
+ /* fall through */
default:
/* For fixed-length NOT NULL 'core' columns,
get a dummy default value from SQL. Note that
@@ -5656,7 +5663,6 @@ static bool innobase_instant_try(
: NULL, true, (*af)->ptr, len,
dict_table_is_comp(user_table));
ut_ad(new_field->field->pack_length() == len);
-
}
}
diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h
index 0aadf59bfb2..29923839ce1 100644
--- a/storage/innobase/include/rem0rec.h
+++ b/storage/innobase/include/rem0rec.h
@@ -291,6 +291,24 @@ inline unsigned rec_get_n_add_field_len(ulint n_add_field)
return n_add_field < 0x80 ? 1 : 2;
}
+/** Get the added field count in a REC_STATUS_INSTANT record.
+@param[in,out] header variable header of a REC_STATUS_INSTANT record
+@return number of added fields */
+inline unsigned rec_get_n_add_field(const byte*& header)
+{
+ unsigned n_fields_add = *--header;
+ if (n_fields_add < 0x80) {
+ ut_ad(rec_get_n_add_field_len(n_fields_add) == 1);
+ return n_fields_add;
+ }
+
+ n_fields_add &= 0x7f;
+ n_fields_add |= unsigned(*--header) << 7;
+ ut_ad(n_fields_add < REC_MAX_N_FIELDS);
+ ut_ad(rec_get_n_add_field_len(n_fields_add) == 2);
+ return n_fields_add;
+}
+
/** Set the added field count in a REC_STATUS_INSTANT record.
@param[in,out] header variable header of a REC_STATUS_INSTANT record
@param[in] n_add number of added fields, minus 1
diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc
index e6b0792c62c..ef17c0746a0 100644
--- a/storage/innobase/rem/rem0rec.cc
+++ b/storage/innobase/rem/rem0rec.cc
@@ -231,24 +231,6 @@ rec_get_n_extern_new(
return(n_extern);
}
-/** Get the added field count in a REC_STATUS_INSTANT record.
-@param[in,out] header variable header of a REC_STATUS_INSTANT record
-@return number of added fields */
-static inline unsigned rec_get_n_add_field(const byte*& header)
-{
- unsigned n_fields_add = *--header;
- if (n_fields_add < 0x80) {
- ut_ad(rec_get_n_add_field_len(n_fields_add) == 1);
- return n_fields_add;
- }
-
- n_fields_add &= 0x7f;
- n_fields_add |= unsigned(*--header) << 7;
- ut_ad(n_fields_add < REC_MAX_N_FIELDS);
- ut_ad(rec_get_n_add_field_len(n_fields_add) == 2);
- return n_fields_add;
-}
-
/** Format of a leaf-page ROW_FORMAT!=REDUNDANT record */
enum rec_leaf_format {
/** Temporary file record */