mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge 10.3 into 10.4
This commit is contained in:
@ -193,6 +193,12 @@ SET DEBUG_SYNC='RESET';
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
INSERT INTO t1 SET a=0;
|
||||
ALTER TABLE t1 ADD COLUMN b INT NOT NULL DEFAULT 2, ADD COLUMN c INT;
|
||||
BEGIN NOT ATOMIC
|
||||
DECLARE c TEXT DEFAULT(SELECT CONCAT('ALTER TABLE t1 ADD (c',
|
||||
GROUP_CONCAT(seq SEPARATOR ' INT, c'), ' INT), ALGORITHM=INSTANT;') FROM seq_1_to_130);
|
||||
EXECUTE IMMEDIATE c;
|
||||
END;
|
||||
$$
|
||||
connection stop_purge;
|
||||
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||
connection default;
|
||||
@ -211,7 +217,7 @@ SET DEBUG_SYNC = 'now SIGNAL logged';
|
||||
connection ddl;
|
||||
connection default;
|
||||
SET DEBUG_SYNC = RESET;
|
||||
SELECT * FROM t1;
|
||||
SELECT a, b, c FROM t1;
|
||||
a b c
|
||||
1 2 NULL
|
||||
2 3 4
|
||||
@ -234,7 +240,7 @@ connection ddl;
|
||||
UPDATE t1 SET b = b + 1 WHERE a = 2;
|
||||
connection default;
|
||||
SET DEBUG_SYNC = RESET;
|
||||
SELECT * FROM t1;
|
||||
SELECT a, b, c FROM t1;
|
||||
a b c
|
||||
1 2 NULL
|
||||
2 3 4
|
||||
@ -258,7 +264,7 @@ ERROR 22004: Invalid use of NULL value
|
||||
disconnect ddl;
|
||||
connection default;
|
||||
SET DEBUG_SYNC = RESET;
|
||||
SELECT * FROM t1;
|
||||
SELECT a, b, c, d FROM t1;
|
||||
a b c d
|
||||
1 2 NULL 1
|
||||
2 3 4 1
|
||||
@ -401,4 +407,4 @@ SELECT variable_value-@old_instant instants
|
||||
FROM information_schema.global_status
|
||||
WHERE variable_name = 'innodb_instant_alter_column';
|
||||
instants
|
||||
29
|
||||
30
|
||||
|
@ -0,0 +1,4 @@
|
||||
[redundant]
|
||||
innodb_default_row_format=redundant
|
||||
[dynamic]
|
||||
innodb_default_row_format=dynamic
|
@ -1,6 +1,7 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
--source include/have_debug_sync.inc
|
||||
--source include/have_sequence.inc
|
||||
|
||||
SET @save_frequency= @@GLOBAL.innodb_purge_rseg_truncate_frequency;
|
||||
SET GLOBAL innodb_purge_rseg_truncate_frequency=1;
|
||||
@ -216,6 +217,15 @@ CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
INSERT INTO t1 SET a=0;
|
||||
ALTER TABLE t1 ADD COLUMN b INT NOT NULL DEFAULT 2, ADD COLUMN c INT;
|
||||
|
||||
DELIMITER $$;
|
||||
BEGIN NOT ATOMIC
|
||||
DECLARE c TEXT DEFAULT(SELECT CONCAT('ALTER TABLE t1 ADD (c',
|
||||
GROUP_CONCAT(seq SEPARATOR ' INT, c'), ' INT), ALGORITHM=INSTANT;') FROM seq_1_to_130);
|
||||
EXECUTE IMMEDIATE c;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
connection stop_purge;
|
||||
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||
|
||||
@ -243,7 +253,7 @@ reap;
|
||||
|
||||
connection default;
|
||||
SET DEBUG_SYNC = RESET;
|
||||
SELECT * FROM t1;
|
||||
SELECT a, b, c FROM t1;
|
||||
ALTER TABLE t1 DROP b, ALGORITHM=INSTANT;
|
||||
connection stop_purge;
|
||||
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||
@ -272,7 +282,7 @@ UPDATE t1 SET b = b + 1 WHERE a = 2;
|
||||
|
||||
connection default;
|
||||
SET DEBUG_SYNC = RESET;
|
||||
SELECT * FROM t1;
|
||||
SELECT a, b, c FROM t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-15872 Crash in online ALTER TABLE...ADD PRIMARY KEY
|
||||
@ -299,7 +309,7 @@ disconnect ddl;
|
||||
|
||||
connection default;
|
||||
SET DEBUG_SYNC = RESET;
|
||||
SELECT * FROM t1;
|
||||
SELECT a, b, c, d FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2017, 2020, MariaDB Corporation.
|
||||
Copyright (c) 2017, 2021, 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
|
||||
@ -1034,12 +1034,14 @@ rec_copy(
|
||||
const rec_offs* offsets);
|
||||
|
||||
/** Determine the size of a data tuple prefix in a temporary file.
|
||||
@tparam redundant_temp whether to use the ROW_FORMAT=REDUNDANT format
|
||||
@param[in] index clustered or secondary index
|
||||
@param[in] fields data fields
|
||||
@param[in] n_fields number of data fields
|
||||
@param[out] extra record header size
|
||||
@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT
|
||||
@return total size, in bytes */
|
||||
template<bool redundant_temp>
|
||||
ulint
|
||||
rec_get_converted_size_temp(
|
||||
const dict_index_t* index,
|
||||
@ -1078,11 +1080,13 @@ rec_init_offsets_temp(
|
||||
MY_ATTRIBUTE((nonnull));
|
||||
|
||||
/** Convert a data tuple prefix to the temporary file format.
|
||||
@tparam redundant_temp whether to use the ROW_FORMAT=REDUNDANT format
|
||||
@param[out] rec record in temporary file format
|
||||
@param[in] index clustered or secondary index
|
||||
@param[in] fields data fields
|
||||
@param[in] n_fields number of data fields
|
||||
@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT */
|
||||
template<bool redundant_temp>
|
||||
void
|
||||
rec_convert_dtuple_to_temp(
|
||||
rec_t* rec,
|
||||
|
@ -247,6 +247,11 @@ row_log_apply(
|
||||
ut_stage_alter_t* stage)
|
||||
MY_ATTRIBUTE((warn_unused_result));
|
||||
|
||||
/** Get the n_core_fields of online log for the index
|
||||
@param index index whose n_core_fields of log to be accessed
|
||||
@return number of n_core_fields */
|
||||
unsigned row_log_get_n_core_fields(const dict_index_t *index);
|
||||
|
||||
#ifdef HAVE_PSI_STAGE_INTERFACE
|
||||
/** Estimate how much work is to be done by the log apply phase
|
||||
of an ALTER TABLE for this index.
|
||||
|
@ -29,6 +29,7 @@ Created 5/30/1994 Heikki Tuuri
|
||||
#include "mtr0log.h"
|
||||
#include "fts0fts.h"
|
||||
#include "trx0sys.h"
|
||||
#include "row0log.h"
|
||||
|
||||
/* PHYSICAL RECORD (OLD STYLE)
|
||||
===========================
|
||||
@ -1095,6 +1096,7 @@ rec_get_nth_field_offs_old(
|
||||
|
||||
/** Determine the size of a data tuple prefix in ROW_FORMAT=COMPACT.
|
||||
@tparam mblob whether the record includes a metadata BLOB
|
||||
@tparam redundant_temp whether to use the ROW_FORMAT=REDUNDANT format
|
||||
@param[in] index record descriptor; dict_table_is_comp()
|
||||
is assumed to hold, even if it doesn't
|
||||
@param[in] dfield array of data fields
|
||||
@ -1103,7 +1105,7 @@ rec_get_nth_field_offs_old(
|
||||
@param[in] status status flags
|
||||
@param[in] temp whether this is a temporary file record
|
||||
@return total size */
|
||||
template<bool mblob = false>
|
||||
template<bool mblob = false, bool redundant_temp = false>
|
||||
static inline
|
||||
ulint
|
||||
rec_get_converted_size_comp_prefix_low(
|
||||
@ -1120,25 +1122,27 @@ rec_get_converted_size_comp_prefix_low(
|
||||
ut_d(ulint n_null = index->n_nullable);
|
||||
ut_ad(status == REC_STATUS_ORDINARY || status == REC_STATUS_NODE_PTR
|
||||
|| status == REC_STATUS_INSTANT);
|
||||
unsigned n_core_fields = redundant_temp
|
||||
? row_log_get_n_core_fields(index)
|
||||
: index->n_core_fields;
|
||||
|
||||
if (mblob) {
|
||||
ut_ad(!temp);
|
||||
ut_ad(index->table->instant);
|
||||
ut_ad(index->is_instant());
|
||||
ut_ad(!redundant_temp && index->is_instant());
|
||||
ut_ad(status == REC_STATUS_INSTANT);
|
||||
ut_ad(n_fields == ulint(index->n_fields) + 1);
|
||||
extra_size += UT_BITS_IN_BYTES(index->n_nullable)
|
||||
+ rec_get_n_add_field_len(n_fields - 1
|
||||
- index->n_core_fields);
|
||||
- n_core_fields);
|
||||
} else if (status == REC_STATUS_INSTANT
|
||||
&& (!temp || n_fields > index->n_core_fields)) {
|
||||
ut_ad(index->is_instant());
|
||||
&& (!temp || n_fields > n_core_fields)) {
|
||||
if (!redundant_temp) { ut_ad(index->is_instant()); }
|
||||
ut_ad(UT_BITS_IN_BYTES(n_null) >= index->n_core_null_bytes);
|
||||
extra_size += UT_BITS_IN_BYTES(index->get_n_nullable(n_fields))
|
||||
+ rec_get_n_add_field_len(n_fields - 1
|
||||
- index->n_core_fields);
|
||||
- n_core_fields);
|
||||
} else {
|
||||
ut_ad(n_fields <= index->n_core_fields);
|
||||
ut_ad(n_fields <= n_core_fields);
|
||||
extra_size += index->n_core_null_bytes;
|
||||
}
|
||||
|
||||
@ -1490,6 +1494,7 @@ rec_convert_dtuple_to_rec_old(
|
||||
|
||||
/** Convert a data tuple into a ROW_FORMAT=COMPACT record.
|
||||
@tparam mblob whether the record includes a metadata BLOB
|
||||
@tparam redundant_temp whether to use the ROW_FORMAT=REDUNDANT format
|
||||
@param[out] rec converted record
|
||||
@param[in] index index
|
||||
@param[in] field data fields to convert
|
||||
@ -1497,7 +1502,7 @@ rec_convert_dtuple_to_rec_old(
|
||||
@param[in] status rec_get_status(rec)
|
||||
@param[in] temp whether to use the format for temporary files
|
||||
in index creation */
|
||||
template<bool mblob = false>
|
||||
template<bool mblob = false, bool redundant_temp = false>
|
||||
static inline
|
||||
void
|
||||
rec_convert_dtuple_to_rec_comp(
|
||||
@ -1514,7 +1519,9 @@ rec_convert_dtuple_to_rec_comp(
|
||||
byte* UNINIT_VAR(lens);
|
||||
ulint UNINIT_VAR(n_node_ptr_field);
|
||||
ulint null_mask = 1;
|
||||
|
||||
const ulint n_core_fields = redundant_temp
|
||||
? row_log_get_n_core_fields(index)
|
||||
: index->n_core_fields;
|
||||
ut_ad(n_fields > 0);
|
||||
ut_ad(temp || dict_table_is_comp(index->table));
|
||||
ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable));
|
||||
@ -1524,11 +1531,10 @@ rec_convert_dtuple_to_rec_comp(
|
||||
if (mblob) {
|
||||
ut_ad(!temp);
|
||||
ut_ad(index->table->instant);
|
||||
ut_ad(index->is_instant());
|
||||
ut_ad(!redundant_temp && index->is_instant());
|
||||
ut_ad(status == REC_STATUS_INSTANT);
|
||||
ut_ad(n_fields == ulint(index->n_fields) + 1);
|
||||
rec_set_n_add_field(nulls, n_fields - 1
|
||||
- index->n_core_fields);
|
||||
rec_set_n_add_field(nulls, n_fields - 1 - n_core_fields);
|
||||
rec_set_heap_no_new(rec, PAGE_HEAP_NO_USER_LOW);
|
||||
rec_set_status(rec, REC_STATUS_INSTANT);
|
||||
n_node_ptr_field = ULINT_UNDEFINED;
|
||||
@ -1537,18 +1543,15 @@ rec_convert_dtuple_to_rec_comp(
|
||||
}
|
||||
switch (status) {
|
||||
case REC_STATUS_INSTANT:
|
||||
ut_ad(index->is_instant());
|
||||
ut_ad(n_fields > index->n_core_fields);
|
||||
rec_set_n_add_field(nulls, n_fields - 1
|
||||
- index->n_core_fields);
|
||||
if (!redundant_temp) { ut_ad(index->is_instant()); }
|
||||
ut_ad(n_fields > n_core_fields);
|
||||
rec_set_n_add_field(nulls, n_fields - 1 - n_core_fields);
|
||||
/* fall through */
|
||||
case REC_STATUS_ORDINARY:
|
||||
ut_ad(n_fields <= dict_index_get_n_fields(index));
|
||||
if (!temp) {
|
||||
rec_set_heap_no_new(rec, PAGE_HEAP_NO_USER_LOW);
|
||||
|
||||
rec_set_status(
|
||||
rec, n_fields == index->n_core_fields
|
||||
rec_set_status(rec, n_fields == n_core_fields
|
||||
? REC_STATUS_ORDINARY
|
||||
: REC_STATUS_INSTANT);
|
||||
}
|
||||
@ -1768,12 +1771,14 @@ rec_convert_dtuple_to_rec(
|
||||
}
|
||||
|
||||
/** Determine the size of a data tuple prefix in a temporary file.
|
||||
@tparam redundant_temp whether to use the ROW_FORMAT=REDUNDANT format
|
||||
@param[in] index clustered or secondary index
|
||||
@param[in] fields data fields
|
||||
@param[in] n_fields number of data fields
|
||||
@param[out] extra record header size
|
||||
@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT
|
||||
@return total size, in bytes */
|
||||
template<bool redundant_temp>
|
||||
ulint
|
||||
rec_get_converted_size_temp(
|
||||
const dict_index_t* index,
|
||||
@ -1782,10 +1787,18 @@ rec_get_converted_size_temp(
|
||||
ulint* extra,
|
||||
rec_comp_status_t status)
|
||||
{
|
||||
return rec_get_converted_size_comp_prefix_low(
|
||||
return rec_get_converted_size_comp_prefix_low<false,redundant_temp>(
|
||||
index, fields, n_fields, extra, status, true);
|
||||
}
|
||||
|
||||
template ulint rec_get_converted_size_temp<false>(
|
||||
const dict_index_t*, const dfield_t*, ulint, ulint*,
|
||||
rec_comp_status_t);
|
||||
|
||||
template ulint rec_get_converted_size_temp<true>(
|
||||
const dict_index_t*, const dfield_t*, ulint, ulint*,
|
||||
rec_comp_status_t);
|
||||
|
||||
/** Determine the offset to each field in temporary file.
|
||||
@param[in] rec temporary file record
|
||||
@param[in] index index of that the record belongs to
|
||||
@ -1838,6 +1851,7 @@ rec_init_offsets_temp(
|
||||
@param[in] n_fields number of data fields
|
||||
@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT
|
||||
*/
|
||||
template<bool redundant_temp>
|
||||
void
|
||||
rec_convert_dtuple_to_temp(
|
||||
rec_t* rec,
|
||||
@ -1846,10 +1860,18 @@ rec_convert_dtuple_to_temp(
|
||||
ulint n_fields,
|
||||
rec_comp_status_t status)
|
||||
{
|
||||
rec_convert_dtuple_to_rec_comp(rec, index, fields, n_fields,
|
||||
status, true);
|
||||
rec_convert_dtuple_to_rec_comp<false,redundant_temp>(
|
||||
rec, index, fields, n_fields, status, true);
|
||||
}
|
||||
|
||||
template void rec_convert_dtuple_to_temp<false>(
|
||||
rec_t*, const dict_index_t*, const dfield_t*,
|
||||
ulint, rec_comp_status_t);
|
||||
|
||||
template void rec_convert_dtuple_to_temp<true>(
|
||||
rec_t*, const dict_index_t*, const dfield_t*,
|
||||
ulint, rec_comp_status_t);
|
||||
|
||||
/** Copy the first n fields of a (copy of a) physical record to a data tuple.
|
||||
The fields are copied into the memory heap.
|
||||
@param[out] tuple data tuple
|
||||
|
@ -353,7 +353,7 @@ row_log_online_op(
|
||||
row_merge_buf_encode(), because here we do not encode
|
||||
extra_size+1 (and reserve 0 as the end-of-chunk marker). */
|
||||
|
||||
size = rec_get_converted_size_temp(
|
||||
size = rec_get_converted_size_temp<false>(
|
||||
index, tuple->fields, tuple->n_fields, &extra_size);
|
||||
ut_ad(size >= extra_size);
|
||||
ut_ad(size <= sizeof log->tail.buf);
|
||||
@ -401,7 +401,7 @@ row_log_online_op(
|
||||
*b++ = (byte) extra_size;
|
||||
}
|
||||
|
||||
rec_convert_dtuple_to_temp(
|
||||
rec_convert_dtuple_to_temp<false>(
|
||||
b + extra_size, index, tuple->fields, tuple->n_fields);
|
||||
b += size;
|
||||
|
||||
@ -743,7 +743,7 @@ row_log_table_delete(
|
||||
old_pk, old_pk->n_fields - 2)->len);
|
||||
ut_ad(DATA_ROLL_PTR_LEN == dtuple_get_nth_field(
|
||||
old_pk, old_pk->n_fields - 1)->len);
|
||||
old_pk_size = rec_get_converted_size_temp(
|
||||
old_pk_size = rec_get_converted_size_temp<false>(
|
||||
new_index, old_pk->fields, old_pk->n_fields,
|
||||
&old_pk_extra_size);
|
||||
ut_ad(old_pk_extra_size < 0x100);
|
||||
@ -756,7 +756,7 @@ row_log_table_delete(
|
||||
*b++ = ROW_T_DELETE;
|
||||
*b++ = static_cast<byte>(old_pk_extra_size);
|
||||
|
||||
rec_convert_dtuple_to_temp(
|
||||
rec_convert_dtuple_to_temp<false>(
|
||||
b + old_pk_extra_size, new_index,
|
||||
old_pk->fields, old_pk->n_fields);
|
||||
|
||||
@ -856,7 +856,7 @@ row_log_table_low_redundant(
|
||||
rec_comp_status_t status = is_instant
|
||||
? REC_STATUS_INSTANT : REC_STATUS_ORDINARY;
|
||||
|
||||
size = rec_get_converted_size_temp(
|
||||
size = rec_get_converted_size_temp<true>(
|
||||
index, tuple->fields, tuple->n_fields, &extra_size, status);
|
||||
if (is_instant) {
|
||||
size++;
|
||||
@ -876,7 +876,7 @@ row_log_table_low_redundant(
|
||||
ut_ad(DATA_ROLL_PTR_LEN == dtuple_get_nth_field(
|
||||
old_pk, old_pk->n_fields - 1)->len);
|
||||
|
||||
old_pk_size = rec_get_converted_size_temp(
|
||||
old_pk_size = rec_get_converted_size_temp<false>(
|
||||
new_index, old_pk->fields, old_pk->n_fields,
|
||||
&old_pk_extra_size);
|
||||
ut_ad(old_pk_extra_size < 0x100);
|
||||
@ -893,7 +893,7 @@ row_log_table_low_redundant(
|
||||
if (old_pk_size) {
|
||||
*b++ = static_cast<byte>(old_pk_extra_size);
|
||||
|
||||
rec_convert_dtuple_to_temp(
|
||||
rec_convert_dtuple_to_temp<false>(
|
||||
b + old_pk_extra_size, new_index,
|
||||
old_pk->fields, old_pk->n_fields);
|
||||
b += old_pk_size;
|
||||
@ -916,7 +916,7 @@ row_log_table_low_redundant(
|
||||
*b = status;
|
||||
}
|
||||
|
||||
rec_convert_dtuple_to_temp(
|
||||
rec_convert_dtuple_to_temp<true>(
|
||||
b + extra_size, index, tuple->fields, tuple->n_fields,
|
||||
status);
|
||||
b += size;
|
||||
@ -1038,7 +1038,7 @@ row_log_table_low(
|
||||
ut_ad(DATA_ROLL_PTR_LEN == dtuple_get_nth_field(
|
||||
old_pk, old_pk->n_fields - 1)->len);
|
||||
|
||||
old_pk_size = rec_get_converted_size_temp(
|
||||
old_pk_size = rec_get_converted_size_temp<false>(
|
||||
new_index, old_pk->fields, old_pk->n_fields,
|
||||
&old_pk_extra_size);
|
||||
ut_ad(old_pk_extra_size < 0x100);
|
||||
@ -1054,7 +1054,7 @@ row_log_table_low(
|
||||
if (old_pk_size) {
|
||||
*b++ = static_cast<byte>(old_pk_extra_size);
|
||||
|
||||
rec_convert_dtuple_to_temp(
|
||||
rec_convert_dtuple_to_temp<false>(
|
||||
b + old_pk_extra_size, new_index,
|
||||
old_pk->fields, old_pk->n_fields);
|
||||
b += old_pk_size;
|
||||
@ -4045,3 +4045,9 @@ row_log_apply(
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
unsigned row_log_get_n_core_fields(const dict_index_t *index)
|
||||
{
|
||||
ut_ad(index->online_log);
|
||||
return index->online_log->n_core_fields;
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ row_merge_buf_encode(
|
||||
ulint size;
|
||||
ulint extra_size;
|
||||
|
||||
size = rec_get_converted_size_temp(
|
||||
size = rec_get_converted_size_temp<false>(
|
||||
index, entry->fields, n_fields, &extra_size);
|
||||
ut_ad(size >= extra_size);
|
||||
|
||||
@ -321,7 +321,7 @@ row_merge_buf_encode(
|
||||
*(*b)++ = (byte) (extra_size + 1);
|
||||
}
|
||||
|
||||
rec_convert_dtuple_to_temp(*b + extra_size, index,
|
||||
rec_convert_dtuple_to_temp<false>(*b + extra_size, index,
|
||||
entry->fields, n_fields);
|
||||
|
||||
*b += size;
|
||||
@ -796,7 +796,7 @@ row_merge_buf_add(
|
||||
ulint size;
|
||||
ulint extra;
|
||||
|
||||
size = rec_get_converted_size_temp(
|
||||
size = rec_get_converted_size_temp<false>(
|
||||
index, entry->fields, n_fields, &extra);
|
||||
|
||||
ut_ad(data_size + extra_size == size);
|
||||
|
Reference in New Issue
Block a user