Merge 10.4 into 10.5

This commit is contained in:
Marko Mäkelä 2020-01-07 14:10:15 +02:00
commit 68fe5f534c
18 changed files with 418 additions and 195 deletions

190
include/intrusive_list.h Normal file
View file

@ -0,0 +1,190 @@
/*
Copyright (c) 2019, 2020, 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 the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
*/
#pragma once
#include <cstddef>
#include <iterator>
namespace intrusive
{
// Derive your class from this struct to insert to a linked list.
template <class Tag= void> struct list_node
{
list_node(list_node *next= NULL, list_node *prev= NULL)
: next(next), prev(prev)
{
}
list_node *next;
list_node *prev;
};
// Modelled after std::list<T>
template <class T, class Tag= void> class list
{
public:
typedef list_node<Tag> ListNode;
class Iterator;
// All containers in C++ should define these types to implement generic
// container interface.
typedef T value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef value_type &reference;
typedef const value_type &const_reference;
typedef T *pointer;
typedef const T *const_pointer;
typedef Iterator iterator;
typedef Iterator const_iterator; /* FIXME */
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const iterator> const_reverse_iterator;
class Iterator
{
public:
// All iterators in C++ should define these types to implement generic
// iterator interface.
typedef std::bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef std::ptrdiff_t difference_type;
typedef T *pointer;
typedef T &reference;
Iterator(ListNode *node) : node_(node) {}
Iterator &operator++()
{
node_= node_->next;
return *this;
}
Iterator operator++(int)
{
Iterator tmp(*this);
operator++();
return tmp;
}
Iterator &operator--()
{
node_= node_->prev;
return *this;
}
Iterator operator--(int)
{
Iterator tmp(*this);
operator--();
return tmp;
}
reference operator*() { return *static_cast<pointer>(node_); }
pointer operator->() { return static_cast<pointer>(node_); }
bool operator==(const Iterator &rhs) { return node_ == rhs.node_; }
bool operator!=(const Iterator &rhs) { return !(*this == rhs); }
private:
ListNode *node_;
friend class list;
};
list() : sentinel_(&sentinel_, &sentinel_), size_(0) {}
reference front() { return *begin(); }
reference back() { return *--end(); }
const_reference front() const { return *begin(); }
const_reference back() const { return *--end(); }
iterator begin() { return iterator(sentinel_.next); }
const_iterator begin() const
{
return iterator(const_cast<ListNode *>(sentinel_.next));
}
iterator end() { return iterator(&sentinel_); }
const_iterator end() const
{
return iterator(const_cast<ListNode *>(&sentinel_));
}
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const { return reverse_iterator(begin()); }
bool empty() const { return size_ == 0; }
size_type size() const { return size_; }
void clear()
{
sentinel_.next= &sentinel_;
sentinel_.prev= &sentinel_;
size_= 0;
}
iterator insert(iterator pos, reference value)
{
ListNode *curr= pos.node_;
ListNode *prev= pos.node_->prev;
prev->next= &value;
curr->prev= &value;
static_cast<ListNode &>(value).prev= prev;
static_cast<ListNode &>(value).next= curr;
++size_;
return iterator(&value);
}
iterator erase(iterator pos)
{
ListNode *prev= pos.node_->prev;
ListNode *next= pos.node_->next;
prev->next= next;
next->prev= prev;
// This is not required for list functioning. But maybe it'll prevent bugs
// and ease debugging.
ListNode *curr= pos.node_;
curr->prev= NULL;
curr->next= NULL;
--size_;
return next;
}
void push_back(reference value) { insert(end(), value); }
void pop_back() { erase(end()); }
void push_front(reference value) { insert(begin(), value); }
void pop_front() { erase(begin()); }
// STL version is O(n) but this is O(1) because an element can't be inserted
// several times in the same intrusive list.
void remove(reference value) { erase(iterator(&value)); }
private:
ListNode sentinel_;
size_type size_;
};
} // namespace intrusive

View file

@ -2847,16 +2847,16 @@ drop table t1;
# MDEV-20922: Adding an order by changes the query results
#
CREATE TABLE t1(a int, b int);
INSERT INTO t1 values (1, 100), (2, 200), (3, 100), (4, 200);
INSERT INTO t1 values (1, 100), (2, 200), (3, 100), (4, 200), (5, 200);
create view v1 as select a, b+1 as x from t1;
SELECT x, COUNT(DISTINCT a) AS y FROM v1 GROUP BY x ORDER BY y;
x y
101 2
201 2
201 3
SELECT b+1 AS x, COUNT(DISTINCT a) AS y FROM t1 GROUP BY x ORDER BY y;
x y
101 2
201 2
201 3
drop view v1;
drop table t1;
#

View file

@ -1959,7 +1959,7 @@ drop table t1;
--echo #
CREATE TABLE t1(a int, b int);
INSERT INTO t1 values (1, 100), (2, 200), (3, 100), (4, 200);
INSERT INTO t1 values (1, 100), (2, 200), (3, 100), (4, 200), (5, 200);
create view v1 as select a, b+1 as x from t1;

View file

@ -2,6 +2,10 @@
-- source include/have_file_key_management_plugin.inc
# embedded does not support restart
-- source include/not_embedded.inc
# MDEV-20839 innodb-redo-badkey sporadically fails on buildbot with page dump
# We only require a debug build to avoid getting page dumps, making use of
# MDEV-19766: Disable page dump output in debug builds
-- source include/have_debug.inc
call mtr.add_suppression("Plugin 'file_key_management'");
call mtr.add_suppression("Plugin 'InnoDB' init function returned error.");

View file

@ -16,6 +16,30 @@ col_1 TEXT
) ENGINE=INNODB ROW_FORMAT=COMPACT;
Warnings:
Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
TRUNCATE TABLE t1;
Warnings:
Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
Warnings:
Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
ALTER TABLE t1 FORCE;
Warnings:
Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
SET innodb_strict_mode = ON;
TRUNCATE TABLE t1;
Warnings:
Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
Warnings:
Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
ALTER TABLE t1 FORCE;
Warnings:
Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
DROP TABLE t1;
SET @@global.log_warnings = 2;
SET innodb_strict_mode = 1;

View file

@ -139,6 +139,7 @@ CHECK TABLE t1;
DROP TABLE t1;
SET @save_algo = @@GLOBAL.innodb_compression_algorithm;
--error 0,ER_WRONG_VALUE_FOR_VAR
SET GLOBAL innodb_compression_algorithm=2;
CREATE TABLE t1(a SERIAL) PAGE_COMPRESSED=1 ENGINE=InnoDB;
INSERT INTO t1 VALUES(1);
@ -170,7 +171,7 @@ INSERT INTO t1 VALUES(2);
SELECT * FROM t1;
--error 0,1231
--error 0,ER_WRONG_VALUE_FOR_VAR
SET GLOBAL innodb_compression_algorithm=3;
FLUSH TABLE t1 FOR EXPORT;
--echo # List before copying files

View file

@ -18,7 +18,15 @@ CREATE TABLE t1 (
,col_10 TEXT
,col_11 TEXT
) ENGINE=INNODB ROW_FORMAT=COMPACT;
--enable_warnings
TRUNCATE TABLE t1;
OPTIMIZE TABLE t1;
ALTER TABLE t1 FORCE;
SET innodb_strict_mode = ON;
TRUNCATE TABLE t1;
OPTIMIZE TABLE t1;
ALTER TABLE t1 FORCE;
DROP TABLE t1;
--disable_warnings
SET @@global.log_warnings = 2;
SET innodb_strict_mode = 1;

View file

@ -4,7 +4,7 @@ use My::Platform;
@ISA = qw(My::Suite);
if (-d '../sql') {
if (-d '../sql' && !&::using_extern()) {
my $src = "$::bindir/plugin/auth_pam/auth_pam_tool";
my $dst = "$::plugindir/auth_pam_tool_dir/auth_pam_tool";
::mkpath( "$::plugindir/auth_pam_tool_dir");

View file

@ -170,6 +170,9 @@ SELECT @@global.wsrep_slave_threads;
SELECT @@global.wsrep_cluster_address;
@@global.wsrep_cluster_address
SELECT @@global.wsrep_on;
@@global.wsrep_on
1
SHOW STATUS LIKE 'threads_connected';
Variable_name Value
Threads_connected 1
@ -183,6 +186,9 @@ SELECT @@global.wsrep_provider;
SELECT @@global.wsrep_cluster_address;
@@global.wsrep_cluster_address
SELECT @@global.wsrep_on;
@@global.wsrep_on
1
SHOW STATUS LIKE 'threads_connected';
Variable_name Value
Threads_connected 1
@ -210,6 +216,9 @@ SELECT @@global.wsrep_provider;
SELECT @@global.wsrep_cluster_address;
@@global.wsrep_cluster_address
gcomm://
SELECT @@global.wsrep_on;
@@global.wsrep_on
1
SHOW STATUS LIKE 'threads_connected';
Variable_name Value
Threads_connected 1

View file

@ -79,6 +79,7 @@ eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER';
SELECT @@global.wsrep_provider;
SELECT @@global.wsrep_slave_threads;
SELECT @@global.wsrep_cluster_address;
SELECT @@global.wsrep_on;
SHOW STATUS LIKE 'threads_connected';
SHOW STATUS LIKE 'wsrep_thread_count';
--echo
@ -90,6 +91,7 @@ eval SET GLOBAL wsrep_provider= '$WSREP_PROVIDER';
--replace_regex /.*libgalera_smm.*/libgalera_smm.so/
SELECT @@global.wsrep_provider;
SELECT @@global.wsrep_cluster_address;
SELECT @@global.wsrep_on;
SHOW STATUS LIKE 'threads_connected';
SHOW STATUS LIKE 'wsrep_thread_count';
--echo
@ -112,6 +114,7 @@ SELECT VARIABLE_VALUE AS EXPECT_2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VA
--replace_regex /.*libgalera_smm.*/libgalera_smm.so/
SELECT @@global.wsrep_provider;
SELECT @@global.wsrep_cluster_address;
SELECT @@global.wsrep_on;
SHOW STATUS LIKE 'threads_connected';
SHOW STATUS LIKE 'wsrep_thread_count';
--echo
@ -134,6 +137,7 @@ SHOW STATUS LIKE 'threads_connected';
#
set wsrep_on=0;
set wsrep_on=1;
--source include/wait_until_connected_again.inc
create user test@localhost;
connect con1,localhost,test;
set auto_increment_increment=10;

View file

@ -2546,7 +2546,7 @@ static void fil_crypt_rotation_list_fill()
}
}
UT_LIST_ADD_LAST(fil_system.rotation_list, space);
fil_system.rotation_list.push_back(*space);
}
}

View file

@ -745,9 +745,7 @@ skip_flush:
if (space->is_in_unflushed_spaces()
&& fil_space_is_flushed(space)) {
UT_LIST_REMOVE(
fil_system.unflushed_spaces,
space);
fil_system.unflushed_spaces.remove(*space);
}
}
@ -1032,7 +1030,7 @@ fil_node_close_to_free(
} else if (space->is_in_unflushed_spaces()
&& fil_space_is_flushed(space)) {
UT_LIST_REMOVE(fil_system.unflushed_spaces, space);
fil_system.unflushed_spaces.remove(*space);
}
node->close();
@ -1055,13 +1053,11 @@ fil_space_detach(
if (space->is_in_unflushed_spaces()) {
ut_ad(!fil_buffering_disabled(space));
UT_LIST_REMOVE(fil_system.unflushed_spaces, space);
fil_system.unflushed_spaces.remove(*space);
}
if (space->is_in_rotation_list()) {
UT_LIST_REMOVE(fil_system.rotation_list, space);
fil_system.rotation_list.remove(*space);
}
UT_LIST_REMOVE(fil_system.space_list, space);
@ -1275,7 +1271,7 @@ fil_space_create(
|| srv_encrypt_tables)) {
/* Key rotation is not enabled, need to inform background
encryption threads. */
UT_LIST_ADD_LAST(fil_system.rotation_list, space);
fil_system.rotation_list.push_back(*space);
mutex_exit(&fil_system.mutex);
os_event_set(fil_crypt_threads_event);
} else {
@ -1578,7 +1574,7 @@ void fil_system_t::close()
{
ut_ad(this == &fil_system);
ut_a(!UT_LIST_GET_LEN(LRU));
ut_a(!UT_LIST_GET_LEN(unflushed_spaces));
ut_a(unflushed_spaces.empty());
ut_a(!UT_LIST_GET_LEN(space_list));
ut_ad(!sys_space);
ut_ad(!temp_space);
@ -3924,8 +3920,8 @@ fil_node_complete_io(fil_node_t* node, const IORequest& type)
node->needs_flush = true;
if (!node->space->is_in_unflushed_spaces()) {
UT_LIST_ADD_FIRST(fil_system.unflushed_spaces,
node->space);
fil_system.unflushed_spaces.push_front(
*node->space);
}
}
}
@ -4328,7 +4324,6 @@ void
fil_flush_file_spaces(
fil_type_t purpose)
{
fil_space_t* space;
ulint* space_ids;
ulint n_space_ids;
@ -4336,30 +4331,25 @@ fil_flush_file_spaces(
mutex_enter(&fil_system.mutex);
n_space_ids = UT_LIST_GET_LEN(fil_system.unflushed_spaces);
n_space_ids = fil_system.unflushed_spaces.size();
if (n_space_ids == 0) {
mutex_exit(&fil_system.mutex);
return;
}
/* Assemble a list of space ids to flush. Previously, we
traversed fil_system.unflushed_spaces and called UT_LIST_GET_NEXT()
on a space that was just removed from the list by fil_flush().
Thus, the space could be dropped and the memory overwritten. */
space_ids = static_cast<ulint*>(
ut_malloc_nokey(n_space_ids * sizeof(*space_ids)));
n_space_ids = 0;
for (space = UT_LIST_GET_FIRST(fil_system.unflushed_spaces);
space;
space = UT_LIST_GET_NEXT(unflushed_spaces, space)) {
for (intrusive::list<fil_space_t, unflushed_spaces_tag_t>::iterator it
= fil_system.unflushed_spaces.begin(),
end = fil_system.unflushed_spaces.end();
it != end; ++it) {
if (space->purpose == purpose
&& !space->is_stopping()) {
space_ids[n_space_ids++] = space->id;
if (it->purpose == purpose && !it->is_stopping()) {
space_ids[n_space_ids++] = it->id;
}
}
@ -4860,8 +4850,8 @@ fil_space_remove_from_keyrotation(fil_space_t* space)
ut_ad(space);
if (!space->referenced() && space->is_in_rotation_list()) {
ut_a(UT_LIST_GET_LEN(fil_system.rotation_list) > 0);
UT_LIST_REMOVE(fil_system.rotation_list, space);
ut_a(!fil_system.rotation_list.empty());
fil_system.rotation_list.remove(*space);
}
}
@ -4877,53 +4867,45 @@ If NULL, use the first fil_space_t on fil_system.space_list.
@param[in] key_version key version of the key state thread
@return pointer to the next fil_space_t.
@retval NULL if this was the last */
fil_space_t*
fil_system_t::keyrotate_next(
fil_space_t* prev_space,
bool recheck,
uint key_version)
fil_space_t *fil_system_t::keyrotate_next(fil_space_t *prev_space,
bool recheck, uint key_version)
{
mutex_enter(&fil_system.mutex);
mutex_enter(&fil_system.mutex);
/* If one of the encryption threads already started the encryption
of the table then don't remove the unencrypted spaces from
rotation list
/* If one of the encryption threads already started the encryption
of the table then don't remove the unencrypted spaces from rotation list
If there is a change in innodb_encrypt_tables variables value then
don't remove the last processed tablespace from the rotation list. */
const bool remove = ((!recheck || prev_space->crypt_data)
&& (!key_version == !srv_encrypt_tables));
If there is a change in innodb_encrypt_tables variables value then
don't remove the last processed tablespace from the rotation list. */
const bool remove= (!recheck || prev_space->crypt_data) &&
!key_version == !srv_encrypt_tables;
intrusive::list<fil_space_t, rotation_list_tag_t>::iterator it=
prev_space == NULL ? fil_system.rotation_list.end() : prev_space;
fil_space_t* space = prev_space;
if (it == fil_system.rotation_list.end())
it= fil_system.rotation_list.begin();
else
{
/* Move on to the next fil_space_t */
prev_space->release();
if (prev_space == NULL) {
space = UT_LIST_GET_FIRST(fil_system.rotation_list);
++it;
/* We can trust that space is not NULL because we
checked list length above */
} else {
/* Move on to the next fil_space_t */
space->release();
while (it != fil_system.rotation_list.end() &&
(UT_LIST_GET_LEN(it->chain) == 0 || it->is_stopping()))
++it;
space = UT_LIST_GET_NEXT(rotation_list, space);
if (remove)
fil_space_remove_from_keyrotation(prev_space);
}
while (space != NULL
&& (UT_LIST_GET_LEN(space->chain) == 0
|| space->is_stopping())) {
space = UT_LIST_GET_NEXT(rotation_list, space);
}
fil_space_t *space= it == fil_system.rotation_list.end() ? NULL : &*it;
if (remove) {
fil_space_remove_from_keyrotation(prev_space);
}
}
if (space)
space->acquire();
if (space != NULL) {
space->acquire();
}
mutex_exit(&fil_system.mutex);
return(space);
mutex_exit(&fil_system.mutex);
return space;
}
/** Determine the block size of the data file.
@ -4978,18 +4960,21 @@ fil_space_found_by_id(
/** Checks that this tablespace in a list of unflushed tablespaces.
@return true if in a list */
bool fil_space_t::is_in_unflushed_spaces() const {
ut_ad(mutex_own(&fil_system.mutex));
bool fil_space_t::is_in_unflushed_spaces() const
{
ut_ad(mutex_own(&fil_system.mutex));
return fil_system.unflushed_spaces.start == this
|| unflushed_spaces.next || unflushed_spaces.prev;
return static_cast<const intrusive::list_node<unflushed_spaces_tag_t> *>(
this)
->next;
}
/** Checks that this tablespace needs key rotation.
@return true if in a rotation list */
bool fil_space_t::is_in_rotation_list() const {
ut_ad(mutex_own(&fil_system.mutex));
bool fil_space_t::is_in_rotation_list() const
{
ut_ad(mutex_own(&fil_system.mutex));
return fil_system.rotation_list.start == this || rotation_list.next
|| rotation_list.prev;
return static_cast<const intrusive::list_node<rotation_list_tag_t> *>(this)
->next;
}

View file

@ -4,7 +4,7 @@ Copyright (c) 2000, 2019, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2012, Facebook Inc.
Copyright (c) 2013, 2019, MariaDB Corporation.
Copyright (c) 2013, 2020, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -3241,17 +3241,6 @@ trx_is_interrupted(
return(trx && trx->mysql_thd && thd_kill_level(trx->mysql_thd));
}
/**********************************************************************//**
Determines if the currently running transaction is in strict mode.
@return TRUE if strict */
ibool
trx_is_strict(
/*==========*/
trx_t* trx) /*!< in: transaction */
{
return(trx && trx->mysql_thd && THDVAR(trx->mysql_thd, strict_mode));
}
/**************************************************************//**
Resets some fields of a m_prebuilt struct. The template is used in fast
retrieval of just those column values MySQL needs in its processing. */
@ -11549,6 +11538,12 @@ create_table_info_t::parse_table_name(
DBUG_RETURN(0);
}
/** @return whether innodb_strict_mode is active */
bool ha_innobase::is_innodb_strict_mode(THD *thd)
{
return THDVAR(thd, strict_mode);
}
/** Determine InnoDB table flags.
If strict_mode=OFF, this will adjust the flags to what should be assumed.
@retval true on success
@ -12831,7 +12826,9 @@ int create_table_info_t::create_table(bool create_fk)
err, m_flags, NULL));
}
if (!row_size_is_acceptable(*m_table)) {
/* In TRUNCATE TABLE, we will merely warn about the maximum
row size being too large. */
if (!row_size_is_acceptable(*m_table, create_fk)) {
DBUG_RETURN(convert_error_code_to_mysql(
DB_TOO_BIG_RECORD, m_flags, NULL));
}
@ -12840,18 +12837,12 @@ int create_table_info_t::create_table(bool create_fk)
}
bool create_table_info_t::row_size_is_acceptable(
const dict_table_t &table) const
const dict_table_t &table, bool strict) const
{
for (dict_index_t *index= dict_table_get_first_index(&table); index;
index= dict_table_get_next_index(index))
{
if (!row_size_is_acceptable(*index))
{
if (!row_size_is_acceptable(*index, strict))
return false;
}
}
return true;
}
@ -13029,7 +13020,7 @@ static void ib_warn_row_too_big(THD *thd, const dict_table_t *table)
}
bool create_table_info_t::row_size_is_acceptable(
const dict_index_t &index) const
const dict_index_t &index, bool strict) const
{
if ((index.type & DICT_FTS) || index.table->is_system_db)
{
@ -13038,7 +13029,7 @@ bool create_table_info_t::row_size_is_acceptable(
return true;
}
const bool strict= THDVAR(m_thd, strict_mode);
const bool innodb_strict_mode= THDVAR(m_thd, strict_mode);
dict_index_t::record_size_info_t info= index.record_size_info();
if (info.row_is_too_big())
@ -13050,9 +13041,9 @@ bool create_table_info_t::row_size_is_acceptable(
const dict_field_t *field= dict_index_get_nth_field(&index, idx);
ut_ad((!field->name) == field->col->is_dropped());
if (strict || global_system_variables.log_warnings > 2)
if (innodb_strict_mode || global_system_variables.log_warnings > 2)
{
ib::error_or_warn eow(strict);
ib::error_or_warn eow(strict && innodb_strict_mode);
if (field->name)
eow << "Cannot add field " << field->name << " in table ";
else
@ -13063,10 +13054,8 @@ bool create_table_info_t::row_size_is_acceptable(
<< info.max_leaf_size << " bytes) for a record on index leaf page.";
}
if (strict)
{
if (strict && innodb_strict_mode)
return false;
}
ib_warn_row_too_big(m_thd, index.table);
}

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2019, MariaDB Corporation.
Copyright (c) 2013, 2020, 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
@ -439,6 +439,13 @@ public:
can_convert_blob(const Field_blob* field,
const Column_definition& new_field) const override;
/** @return whether innodb_strict_mode is active */
static bool is_innodb_strict_mode(THD* thd);
/** @return whether innodb_strict_mode is active */
bool is_innodb_strict_mode()
{ return is_innodb_strict_mode(m_user_thd); }
protected:
dberr_t innobase_get_autoinc(ulonglong* value);
dberr_t innobase_lock_autoinc();
@ -682,9 +689,11 @@ public:
void allocate_trx();
/** Checks that every index have sane size. Depends on strict mode */
bool row_size_is_acceptable(const dict_table_t& table) const;
bool row_size_is_acceptable(const dict_table_t& table,
bool strict) const;
/** Checks that given index have sane size. Depends on strict mode */
bool row_size_is_acceptable(const dict_index_t& index) const;
bool row_size_is_acceptable(const dict_index_t& index,
bool strict) const;
/** Determines InnoDB table flags.
If strict_mode=OFF, this will adjust the flags to what should be assumed.

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2019, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2019, MariaDB Corporation.
Copyright (c) 2013, 2020, 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
@ -124,6 +124,15 @@ static const alter_table_operations INNOBASE_ALTER_NOCREATE
= ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX
| ALTER_DROP_UNIQUE_INDEX;
/** Operations that InnoDB cares about and can perform without validation */
static const alter_table_operations INNOBASE_ALTER_NOVALIDATE
= INNOBASE_ALTER_NOCREATE
| ALTER_VIRTUAL_COLUMN_ORDER
| ALTER_COLUMN_NAME
| INNOBASE_FOREIGN_OPERATIONS
| ALTER_COLUMN_UNVERSIONED
| ALTER_DROP_VIRTUAL_COLUMN;
/** Operations that InnoDB cares about and can perform without rebuild */
static const alter_table_operations INNOBASE_ALTER_NOREBUILD
= INNOBASE_ONLINE_CREATE
@ -2286,7 +2295,7 @@ next_column:
const bool supports_instant = instant_alter_column_possible(
*m_prebuilt->table, ha_alter_info, table, altered_table,
trx_is_strict(m_prebuilt->trx));
is_innodb_strict_mode());
if (add_drop_v_cols) {
ulonglong flags = ha_alter_info->handler_flags;
@ -6437,7 +6446,7 @@ new_clustered_failed:
if (ctx->need_rebuild() && instant_alter_column_possible(
*user_table, ha_alter_info, old_table, altered_table,
trx_is_strict(ctx->trx))) {
ha_innobase::is_innodb_strict_mode(ctx->trx->mysql_thd))) {
for (uint a = 0; a < ctx->num_to_add_index; a++) {
ctx->add_index[a]->table = ctx->new_table;
error = dict_index_add_to_cache(
@ -6670,7 +6679,15 @@ error_handling_drop_uncached_1:
}
ctx->add_index[a] = index;
if (!info.row_size_is_acceptable(*index)) {
/* For ALTER TABLE...FORCE or OPTIMIZE TABLE,
we may only issue warnings, because there will
be no schema change from the user perspective. */
if (!info.row_size_is_acceptable(
*index,
!!(ha_alter_info->handler_flags
& ~(INNOBASE_INPLACE_IGNORE
| INNOBASE_ALTER_NOVALIDATE
| ALTER_RECREATE_TABLE)))) {
error = DB_TOO_BIG_RECORD;
goto error_handling_drop_uncached_1;
}
@ -6771,7 +6788,7 @@ error_handling_drop_uncached:
DBUG_ASSERT(index != ctx->add_index[a]);
}
ctx->add_index[a]= index;
if (!info.row_size_is_acceptable(*index)) {
if (!info.row_size_is_acceptable(*index, true)) {
error = DB_TOO_BIG_RECORD;
goto error_handling_drop_uncached;
}
@ -6824,7 +6841,7 @@ error_handling_drop_uncached:
}
}
} else if (ctx->is_instant()
&& !info.row_size_is_acceptable(*user_table)) {
&& !info.row_size_is_acceptable(*user_table, true)) {
error = DB_TOO_BIG_RECORD;
goto error_handling;
}

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, 2019, MariaDB Corporation.
Copyright (c) 2018, 2020, 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
@ -29,7 +29,8 @@ Created 2013-03-16 Sunny Bains
#include "mem0mem.h"
#include "dyn0types.h"
#include "ut0lst.h"
#include "intrusive_list.h"
/** Class that manages dynamic buffers. It uses a UT_LIST of
mtr_buf_t::block_t instances. We don't use STL containers in
@ -40,17 +41,11 @@ backend for the custom allocator because we would like the data in
the blocks to be contiguous. */
class mtr_buf_t {
public:
class block_t;
typedef UT_LIST_NODE_T(block_t) block_node_t;
typedef UT_LIST_BASE_NODE_T(block_t) block_list_t;
/** SIZE - sizeof(m_node) + sizeof(m_used) */
enum { MAX_DATA_SIZE = DYN_ARRAY_DATA_SIZE
- sizeof(block_node_t) + sizeof(ib_uint32_t) };
- sizeof(intrusive::list_node<>) + sizeof(uint32_t) };
class block_t {
class block_t : public intrusive::list_node<> {
public:
block_t()
@ -158,9 +153,6 @@ public:
/** Storage */
byte m_data[MAX_DATA_SIZE];
/** Doubly linked list node. */
block_node_t m_node;
/** number of data bytes used in this block;
DYN_BLOCK_FULL_FLAG is set when the block becomes full */
uint32_t m_used;
@ -168,13 +160,14 @@ public:
friend class mtr_buf_t;
};
typedef intrusive::list<block_t> list_t;
/** Default constructor */
mtr_buf_t()
:
m_heap(),
m_size()
{
UT_LIST_INIT(m_list, &block_t::m_node);
push_back(&m_first_block);
}
@ -192,11 +185,11 @@ public:
m_heap = NULL;
/* Initialise the list and add the first block. */
UT_LIST_INIT(m_list, &block_t::m_node);
push_back(&m_first_block);
m_list.clear();
m_list.push_back(m_first_block);
} else {
m_first_block.init();
ut_ad(UT_LIST_GET_LEN(m_list) == 1);
ut_ad(m_list.size() == 1);
}
m_size = 0;
@ -228,7 +221,7 @@ public:
@param ptr end of used space */
void close(const byte* ptr)
{
ut_ad(UT_LIST_GET_LEN(m_list) > 0);
ut_ad(!m_list.empty());
block_t* block = back();
m_size -= block->used();
@ -310,11 +303,10 @@ public:
#ifdef UNIV_DEBUG
ulint total_size = 0;
for (const block_t* block = UT_LIST_GET_FIRST(m_list);
block != NULL;
block = UT_LIST_GET_NEXT(m_node, block)) {
total_size += block->used();
for (typename list_t::iterator it = m_list.begin(),
end = m_list.end();
it != end; ++it) {
total_size += it->used();
}
ut_ad(total_size == m_size);
@ -328,12 +320,12 @@ public:
template <typename Functor>
bool for_each_block(Functor& functor) const
{
for (const block_t* block = UT_LIST_GET_FIRST(m_list);
block != NULL;
block = UT_LIST_GET_NEXT(m_node, block)) {
for (typename list_t::iterator it = m_list.begin(),
end = m_list.end();
it != end; ++it) {
if (!functor(block)) {
return(false);
if (!functor(&*it)) {
return false;
}
}
@ -346,12 +338,12 @@ public:
template <typename Functor>
bool for_each_block_in_reverse(Functor& functor) const
{
for (block_t* block = UT_LIST_GET_LAST(m_list);
block != NULL;
block = UT_LIST_GET_PREV(m_node, block)) {
for (typename list_t::reverse_iterator it = m_list.rbegin(),
end = m_list.rend();
it != end; ++it) {
if (!functor(block)) {
return(false);
if (!functor(&*it)) {
return false;
}
}
@ -364,12 +356,12 @@ public:
template <typename Functor>
bool for_each_block_in_reverse(const Functor& functor) const
{
for (block_t* block = UT_LIST_GET_LAST(m_list);
block != NULL;
block = UT_LIST_GET_PREV(m_node, block)) {
for (typename list_t::reverse_iterator it = m_list.rbegin(),
end = m_list.rend();
it != end; ++it) {
if (!functor(block)) {
return(false);
if (!functor(&*it)) {
return false;
}
}
@ -381,8 +373,7 @@ public:
block_t* front()
MY_ATTRIBUTE((warn_unused_result))
{
ut_ad(UT_LIST_GET_LEN(m_list) > 0);
return(UT_LIST_GET_FIRST(m_list));
return &m_list.front();
}
/**
@ -403,14 +394,13 @@ private:
void push_back(block_t* block)
{
block->init();
UT_LIST_ADD_LAST(m_list, block);
m_list.push_back(*block);
}
/** @return the last block in the list */
block_t* back() const
{
return(UT_LIST_GET_LAST(m_list));
return &const_cast<block_t&>(m_list.back());
}
/*
@ -433,25 +423,22 @@ private:
@return the block containing the pos. */
block_t* find(ulint& pos)
{
block_t* block;
ut_ad(!m_list.empty());
ut_ad(UT_LIST_GET_LEN(m_list) > 0);
for (typename list_t::iterator it = m_list.begin(),
end = m_list.end();
it != end; ++it) {
for (block = UT_LIST_GET_FIRST(m_list);
block != NULL;
block = UT_LIST_GET_NEXT(m_node, block)) {
if (pos < it->used()) {
ut_ad(it->used() >= pos);
if (pos < block->used()) {
break;
return &*it;
}
pos -= block->used();
pos -= it->used();
}
ut_ad(block != NULL);
ut_ad(block->used() >= pos);
return(block);
return NULL;
}
/**
@ -477,7 +464,7 @@ private:
mem_heap_t* m_heap;
/** Allocated blocks */
block_list_t m_list;
list_t m_list;
/** Total size used by all blocks */
ulint m_size;

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2019, MariaDB Corporation.
Copyright (c) 2013, 2020, 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
@ -34,10 +34,14 @@ Created 10/25/1995 Heikki Tuuri
#include "hash0hash.h"
#include "log0recv.h"
#include "dict0types.h"
#include "intrusive_list.h"
#ifdef UNIV_LINUX
# include <set>
#endif
struct unflushed_spaces_tag_t;
struct rotation_list_tag_t;
/** whether to reduce redo logging during ALTER TABLE */
extern my_bool innodb_log_optimize_ddl;
// Forward declaration
@ -78,7 +82,13 @@ struct fil_node_t;
#endif
/** Tablespace or log data space */
struct fil_space_t {
#ifndef UNIV_INNOCHECKSUM
struct fil_space_t : intrusive::list_node<unflushed_spaces_tag_t>,
intrusive::list_node<rotation_list_tag_t>
#else
struct fil_space_t
#endif
{
#ifndef UNIV_INNOCHECKSUM
ulint id; /*!< space id */
hash_node_t hash; /*!< hash chain node */
@ -148,9 +158,6 @@ struct fil_space_t {
std::atomic<ulint> n_pending_ios;
rw_lock_t latch; /*!< latch protecting the file space storage
allocation */
UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
/*!< list of spaces with at least one unflushed
file we have written to */
UT_LIST_NODE_T(fil_space_t) named_spaces;
/*!< list of spaces for which MLOG_FILE_NAME
records have been issued */
@ -159,8 +166,6 @@ struct fil_space_t {
bool is_in_unflushed_spaces() const;
UT_LIST_NODE_T(fil_space_t) space_list;
/*!< list of all spaces */
/** other tablespaces needing key rotation */
UT_LIST_NODE_T(fil_space_t) rotation_list;
/** Checks that this tablespace needs key rotation.
@return true if in a rotation list */
bool is_in_rotation_list() const;
@ -268,7 +273,7 @@ struct fil_space_t {
void release_for_io() { ut_ad(pending_io()); n_pending_ios--; }
/** @return whether I/O is pending */
bool pending_io() const { return n_pending_ios; }
#endif
#endif /* !UNIV_INNOCHECKSUM */
/** FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags;
check fsp0types.h to more info about flags. */
ulint flags;
@ -888,8 +893,6 @@ struct fil_system_t {
{
UT_LIST_INIT(LRU, &fil_node_t::LRU);
UT_LIST_INIT(space_list, &fil_space_t::space_list);
UT_LIST_INIT(rotation_list, &fil_space_t::rotation_list);
UT_LIST_INIT(unflushed_spaces, &fil_space_t::unflushed_spaces);
UT_LIST_INIT(named_spaces, &fil_space_t::named_spaces);
}
@ -941,8 +944,8 @@ public:
not put to this list: they are opened
after the startup, and kept open until
shutdown */
UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
/*!< base node for the list of those
intrusive::list<fil_space_t, unflushed_spaces_tag_t> unflushed_spaces;
/*!< list of those
tablespaces whose files contain
unflushed writes; those spaces have
at least one file node where
@ -962,7 +965,7 @@ public:
record has been written since
the latest redo log checkpoint.
Protected only by log_sys.mutex. */
UT_LIST_BASE_NODE_T(fil_space_t) rotation_list;
intrusive::list<fil_space_t, rotation_list_tag_t> rotation_list;
/*!< list of all file spaces needing
key rotation.*/

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2019, MariaDB Corporation.
Copyright (c) 2015, 2020, 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
@ -342,13 +342,6 @@ bool
trx_is_interrupted(
/*===============*/
const trx_t* trx); /*!< in: transaction */
/**********************************************************************//**
Determines if the currently running transaction is in strict mode.
@return TRUE if strict */
ibool
trx_is_strict(
/*==========*/
trx_t* trx); /*!< in: transaction */
/*******************************************************************//**
Calculates the "weight" of a transaction. The weight of one transaction