Merge 10.4 into 10.5

This commit is contained in:
Marko Mäkelä 2020-05-20 17:46:05 +03:00
commit 5ece2155cb
37 changed files with 466 additions and 312 deletions

View File

@ -5535,7 +5535,7 @@ static bool xtrabackup_prepare_func(char** argv)
error_cleanup: error_cleanup:
xb_filters_free(); xb_filters_free();
return ok; return ok && !ib::error::was_logged();
} }
/************************************************************************** /**************************************************************************

View File

@ -483,7 +483,7 @@ sub mtr_report_stats ($$$$) {
$comment =~ s/[\"]//g; $comment =~ s/[\"]//g;
# if a test case has to be retried it should have the result MTR_RES_FAILED in jUnit XML # if a test case has to be retried it should have the result MTR_RES_FAILED in jUnit XML
if ($test->{'result'} eq "MTR_RES_FAILED" || $test->{'retries'}) { if ($test->{'result'} eq "MTR_RES_FAILED" || $test->{'retries'} > 0) {
my $logcontents = $test->{'logfile-failed'} || $test->{'logfile'}; my $logcontents = $test->{'logfile-failed'} || $test->{'logfile'};
$xml_report .= qq(>\n\t\t\t<failure message="" type="MTR_RES_FAILED">\n<![CDATA[$logcontents]]>\n\t\t\t</failure>\n\t\t</testcase>\n); $xml_report .= qq(>\n\t\t\t<failure message="" type="MTR_RES_FAILED">\n<![CDATA[$logcontents]]>\n\t\t\t</failure>\n\t\t</testcase>\n);
@ -649,6 +649,8 @@ sub mtr_error (@) {
} }
else else
{ {
use Carp qw(cluck);
cluck "Error happened" if $verbose > 0;
exit(1); exit(1);
} }
} }

View File

@ -2815,6 +2815,31 @@ SET DEFAULT_STORAGE_ENGINE=Default;
# End of 10.2 tests # End of 10.2 tests
# #
# #
# Start of 10.3 tests
#
#
# MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query
#
SET NAMES utf8;
CREATE TABLE t1 (a TEXT CHARACTER SET utf16);
SELECT * FROM (VALUES (1) UNION SELECT * FROM t1) AS t;
1
1
DROP TABLE t1;
VALUES (1) UNION SELECT _utf16 0x0020;
1
1
VALUES ('') UNION SELECT _utf16 0x0020 COLLATE utf16_bin;
VALUES ('') UNION VALUES ( _utf16 0x0020 COLLATE utf16_bin);
#
# End of 10.3 tests
#
#
# Start of 10.5 tests # Start of 10.5 tests
# #
# #

View File

@ -935,6 +935,27 @@ let $coll_pad='utf16_bin';
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query
--echo #
SET NAMES utf8;
CREATE TABLE t1 (a TEXT CHARACTER SET utf16);
SELECT * FROM (VALUES (1) UNION SELECT * FROM t1) AS t;
DROP TABLE t1;
VALUES (1) UNION SELECT _utf16 0x0020;
VALUES ('') UNION SELECT _utf16 0x0020 COLLATE utf16_bin;
VALUES ('') UNION VALUES ( _utf16 0x0020 COLLATE utf16_bin);
--echo #
--echo # End of 10.3 tests
--echo #
--echo # --echo #
--echo # Start of 10.5 tests --echo # Start of 10.5 tests

View File

@ -11324,6 +11324,18 @@ SELECT x AS 5天内最近一次登录时间 FROM t1;
1 1
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query
#
SET NAMES utf8;
VALUES (_latin1 0xDF) UNION SELECT _utf8'a' COLLATE utf8_bin;
_latin1 0xDF
ß
a
VALUES (_latin1 0xDF) UNION VALUES(_utf8'a' COLLATE utf8_bin);
_latin1 0xDF
ß
a
#
# End of 10.3 tests # End of 10.3 tests
# #
# #

View File

@ -2257,6 +2257,13 @@ INSERT INTO t1 VALUES (1);
SELECT x AS 5天内最近一次登录时间 FROM t1; SELECT x AS 5天内最近一次登录时间 FROM t1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-22391 Assertion `0' failed in Item_type_holder::val_str on utf16 charset table query
--echo #
SET NAMES utf8;
VALUES (_latin1 0xDF) UNION SELECT _utf8'a' COLLATE utf8_bin;
VALUES (_latin1 0xDF) UNION VALUES(_utf8'a' COLLATE utf8_bin);
--echo # --echo #
--echo # End of 10.3 tests --echo # End of 10.3 tests

View File

@ -5472,6 +5472,23 @@ drop procedure p;
drop view v1; drop view v1;
drop table t1; drop table t1;
# #
# MDEV-22591 Debug build crashes on EXECUTE IMMEDIATE '... WHERE ?' USING IGNORE
#
CREATE TABLE t1 (a INT);
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE ?' USING IGNORE;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'SELECT * FROM t1 HAVING ?' USING IGNORE;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE ?' USING 0;
a
EXECUTE IMMEDIATE 'SELECT * FROM t1 HAVING ?' USING 0;
a
DROP TABLE t1;
EXECUTE IMMEDIATE 'SHOW DATABASES WHERE ?' USING DEFAULT;
ERROR HY000: Default/ignore value is not supported for such parameter usage
EXECUTE IMMEDIATE 'SHOW DATABASES WHERE ?' USING 0;
Database
#
# End of 10.2 tests # End of 10.2 tests
# #
# #

View File

@ -4914,6 +4914,23 @@ drop procedure p;
drop view v1; drop view v1;
drop table t1; drop table t1;
--echo #
--echo # MDEV-22591 Debug build crashes on EXECUTE IMMEDIATE '... WHERE ?' USING IGNORE
--echo #
CREATE TABLE t1 (a INT);
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE ?' USING IGNORE;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'SELECT * FROM t1 HAVING ?' USING IGNORE;
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE ?' USING 0;
EXECUTE IMMEDIATE 'SELECT * FROM t1 HAVING ?' USING 0;
DROP TABLE t1;
--error ER_INVALID_DEFAULT_PARAM
EXECUTE IMMEDIATE 'SHOW DATABASES WHERE ?' USING DEFAULT;
EXECUTE IMMEDIATE 'SHOW DATABASES WHERE ?' USING 0;
--echo # --echo #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #

View File

@ -0,0 +1,20 @@
CREATE DATABASE test1;
CREATE PROCEDURE test1.sp3() BEGIN END;
SHOW PROCEDURE STATUS;
Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
mtr add_suppression PROCEDURE root@localhost # # DEFINER utf8 utf8_general_ci latin1_swedish_ci
mtr check_testcase PROCEDURE root@localhost # # DEFINER utf8 utf8_general_ci latin1_swedish_ci
mtr check_warnings PROCEDURE root@localhost # # DEFINER utf8 utf8_general_ci latin1_swedish_ci
mysql AddGeometryColumn PROCEDURE mariadb.sys@localhost # # INVOKER latin1 latin1_swedish_ci latin1_swedish_ci
mysql DropGeometryColumn PROCEDURE mariadb.sys@localhost # # INVOKER latin1 latin1_swedish_ci latin1_swedish_ci
test sp2 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci
test1 sp1 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci
test1 sp3 PROCEDURE root@localhost # # DEFINER latin1 latin1_swedish_ci latin1_swedish_ci
DROP PROCEDURE sp2;
DROP DATABASE test1;
select count(*) from mysql.event;
count(*)
416
flush tables;
show events;
truncate table mysql.event;

37
mysql-test/main/sp2.test Normal file

File diff suppressed because one or more lines are too long

View File

@ -785,8 +785,14 @@ sub run_test_server ($$$) {
if ( $result->is_failed() ) { if ( $result->is_failed() ) {
my $worker_logdir= $result->{savedir}; my $worker_logdir= $result->{savedir};
my $log_file_name=dirname($worker_logdir)."/".$result->{shortname}.".log"; my $log_file_name=dirname($worker_logdir)."/".$result->{shortname}.".log";
$result->{'logfile-failed'} = mtr_lastlinesfromfile($log_file_name, 20);
rename $log_file_name,$log_file_name.".failed"; if (-e $log_file_name) {
$result->{'logfile-failed'} = mtr_lastlinesfromfile($log_file_name, 20);
} else {
$result->{'logfile-failed'} = "";
}
rename $log_file_name, $log_file_name.".failed";
} }
delete($result->{result}); delete($result->{result});
$result->{retries}= $retries+1; $result->{retries}= $retries+1;

View File

@ -20,5 +20,8 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
SET @binlog_fragment_0='012345'; SET @binlog_fragment_0='012345';
BINLOG @binlog_fragment_0, @binlog_fragment_not_exist; BINLOG @binlog_fragment_0, @binlog_fragment_not_exist;
ERROR 42000: Incorrect argument type to variable 'binlog_fragment_not_exist' ERROR 42000: Incorrect argument type to variable 'binlog_fragment_not_exist'
SET @a= '42';
BINLOG @a, @a;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use
# Cleanup # Cleanup
DROP TABLE t; DROP TABLE t;

View File

@ -41,6 +41,11 @@ SET @binlog_fragment_0='012345';
--error ER_WRONG_TYPE_FOR_VAR --error ER_WRONG_TYPE_FOR_VAR
BINLOG @binlog_fragment_0, @binlog_fragment_not_exist; BINLOG @binlog_fragment_0, @binlog_fragment_not_exist;
# MDEV-22520
SET @a= '42';
--error ER_SYNTAX_ERROR
BINLOG @a, @a;
--echo # Cleanup --echo # Cleanup
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql --remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.sql
DROP TABLE t; DROP TABLE t;

View File

@ -1,26 +1,24 @@
connection node_2; connection node_2;
connection node_1; connection node_1;
connection node_1; connection node_1;
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; CREATE TABLE ten (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
connection node_2; connection node_2;
SET SESSION wsrep_retry_autocommit = 0; SET SESSION wsrep_retry_autocommit = 0;
INSERT INTO t1(f1) SELECT 1 FROM ten as a1, ten AS a2; INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6, ten AS a7, ten AS a8;
set debug_sync='ha_commit_trans_after_prepare WAIT_FOR go';
INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6;;
connection node_1; connection node_1;
TRUNCATE TABLE t1;; TRUNCATE TABLE t1;;
connection node_1;
connection node_2; connection node_2;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_2;
SELECT COUNT(*) = 0 FROM t1;
COUNT(*) = 0
1
connection node_1; connection node_1;
SELECT COUNT(*) = 0 FROM t1; connection node_2;
COUNT(*) = 0 SELECT COUNT(*) AS EXPECT_0 FROM t1;
1 EXPECT_0
0
connection node_1;
SELECT COUNT(*) AS EXPECT_0 FROM t1;
EXPECT_0
0
DROP TABLE t1; DROP TABLE t1;
DROP TABLE ten; DROP TABLE ten;

View File

@ -4,50 +4,42 @@
# #
--source include/galera_cluster.inc --source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc --source include/have_debug_sync.inc
--source include/not_embedded.inc --source include/have_debug.inc
# #
# INSERT and TRUNCATE on different nodes # INSERT and TRUNCATE on different nodes
# #
--connection node_1 --connection node_1
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; CREATE TABLE ten (f1 INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); INSERT INTO ten VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB;
# Insert 1m rows
--connection node_2 --connection node_2
--let $wait_condition = SELECT COUNT(*) = 10 FROM ten; --let $wait_condition = SELECT COUNT(*) = 10 FROM ten;
--source include/wait_condition.inc --source include/wait_condition.inc
# Prevent autocommit retring from masking the deadlock error we expect to get # Prevent autocommit retring from masking the deadlock error we expect to get
SET SESSION wsrep_retry_autocommit = 0; SET SESSION wsrep_retry_autocommit = 0;
INSERT INTO t1(f1) SELECT 1 FROM ten as a1, ten AS a2; --send INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6, ten AS a7, ten AS a8
set debug_sync='ha_commit_trans_after_prepare WAIT_FOR go';
--send INSERT INTO t1 (f1) SELECT 1 FROM ten AS a1, ten AS a2, ten AS a3, ten AS a4, ten AS a5, ten AS a6;
--connection node_1 --connection node_1
# Wait for a above insert to start
--let $wait_condition = SELECT COUNT(*) >= 100 from t1;
--source include/wait_condition.inc
--send TRUNCATE TABLE t1; --send TRUNCATE TABLE t1;
--connection node_1
--reap
--connection node_2 --connection node_2
--error ER_LOCK_DEADLOCK --error ER_LOCK_DEADLOCK
--reap --reap
--connection node_1
--reap
--connection node_2 --connection node_2
SELECT COUNT(*) = 0 FROM t1; SELECT COUNT(*) AS EXPECT_0 FROM t1;
--connection node_1 --connection node_1
SELECT COUNT(*) = 0 FROM t1; SELECT COUNT(*) AS EXPECT_0 FROM t1;
DROP TABLE t1; DROP TABLE t1;
DROP TABLE ten; DROP TABLE ten;

View File

@ -17,13 +17,12 @@ set global debug_dbug=@old_dbug;
connection master; connection master;
### Dump thread is hanging despite slave has gracefully exited.
let $id=`SELECT id from information_schema.processlist where command='Binlog Dump'`; let $id=`SELECT id from information_schema.processlist where command='Binlog Dump'`;
if ($id) { if ($id) {
replace_result $id DUMP_THREAD; replace_result $id DUMP_THREAD;
eval kill $id; eval kill $id;
let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Binlog Dump'; let $wait_condition= SELECT count(*)=0 from information_schema.processlist where command='Killed';
source include/wait_condition.inc; source include/wait_condition.inc;
} }

View File

@ -700,7 +700,7 @@ VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Number of threads performing background key rotation VARIABLE_COMMENT Number of threads performing background key rotation
NUMERIC_MIN_VALUE 0 NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 4294967295 NUMERIC_MAX_VALUE 255
NUMERIC_BLOCK_SIZE 0 NUMERIC_BLOCK_SIZE 0
ENUM_VALUE_LIST NULL ENUM_VALUE_LIST NULL
READ_ONLY NO READ_ONLY NO

View File

@ -7197,6 +7197,23 @@ public:
enum Type type() const { return TYPE_HOLDER; } enum Type type() const { return TYPE_HOLDER; }
const TYPELIB *get_typelib() const { return enum_set_typelib; } const TYPELIB *get_typelib() const { return enum_set_typelib; }
/*
When handling a query like this:
VALUES ('') UNION VALUES( _utf16 0x0020 COLLATE utf16_bin);
Item_type_holder can be passed to
Type_handler_xxx::Item_hybrid_func_fix_attributes()
We don't want the latter to perform character set conversion of a
Item_type_holder by calling its val_str(), which calls DBUG_ASSERT(0).
Let's override const_item() and is_expensive() to avoid this.
Note, Item_hybrid_func_fix_attributes() could probably
have a new argument to distinguish what we need:
- (a) aggregate data type attributes only
- (b) install converters after attribute aggregation
So st_select_lex_unit::join_union_type_attributes() could
ask it to do (a) only, without (b).
*/
bool const_item() const { return false; }
bool is_expensive() { return true; }
double val_real(); double val_real();
longlong val_int(); longlong val_int();
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);

View File

@ -158,8 +158,9 @@ int binlog_defragment(THD *thd)
memcpy(const_cast<char*>(thd->lex->comment.str) + gathered_length, entry[k]->value, memcpy(const_cast<char*>(thd->lex->comment.str) + gathered_length, entry[k]->value,
entry[k]->length); entry[k]->length);
gathered_length += entry[k]->length; gathered_length += entry[k]->length;
update_hash(entry[k], true, NULL, 0, STRING_RESULT, &my_charset_bin, 0);
} }
for (uint k=0; k < 2; k++)
update_hash(entry[k], true, NULL, 0, STRING_RESULT, &my_charset_bin, 0);
DBUG_ASSERT(gathered_length == thd->lex->comment.length); DBUG_ASSERT(gathered_length == thd->lex->comment.length);

View File

@ -2161,7 +2161,9 @@ dict_index_remove_from_cache_low(
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N); ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
ut_ad(mutex_own(&dict_sys.mutex)); ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(table->id); ut_ad(table->id);
#ifdef BTR_CUR_HASH_ADAPT
ut_ad(!index->freed()); ut_ad(!index->freed());
#endif /* BTR_CUR_HASH_ADAPT */
/* No need to acquire the dict_index_t::lock here because /* No need to acquire the dict_index_t::lock here because
there can't be any active operations on this index (or table). */ there can't be any active operations on this index (or table). */

View File

@ -2681,10 +2681,7 @@ fseg_free_extent(
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE); == FSEG_MAGIC_N_VALUE);
ut_d(space->modify_check(*mtr)); ut_d(space->modify_check(*mtr));
ut_d(ulint first_page_in_extent = page - (page % FSP_EXTENT_SIZE));
#if defined BTR_CUR_HASH_ADAPT || defined UNIV_DEBUG
const ulint first_page_in_extent = page - (page % FSP_EXTENT_SIZE);
#endif /* BTR_CUR_HASH_ADAPT || UNIV_DEBUG */
const uint16_t xoffset= uint16_t(descr - xdes->frame + XDES_FLST_NODE); const uint16_t xoffset= uint16_t(descr - xdes->frame + XDES_FLST_NODE);
const uint16_t ioffset= uint16_t(seg_inode - iblock->frame); const uint16_t ioffset= uint16_t(seg_inode - iblock->frame);

View File

@ -583,7 +583,7 @@ fts_cache_init(
mutex_enter((ib_mutex_t*) &cache->deleted_lock); mutex_enter((ib_mutex_t*) &cache->deleted_lock);
cache->deleted_doc_ids = ib_vector_create( cache->deleted_doc_ids = ib_vector_create(
cache->sync_heap, sizeof(fts_update_t), 4); cache->sync_heap, sizeof(doc_id_t), 4);
mutex_exit((ib_mutex_t*) &cache->deleted_lock); mutex_exit((ib_mutex_t*) &cache->deleted_lock);
/* Reset the cache data for all the FTS indexes. */ /* Reset the cache data for all the FTS indexes. */
@ -2592,11 +2592,11 @@ dberr_t
fts_cmp_set_sync_doc_id( fts_cmp_set_sync_doc_id(
/*====================*/ /*====================*/
const dict_table_t* table, /*!< in: table */ const dict_table_t* table, /*!< in: table */
doc_id_t doc_id_cmp, /*!< in: Doc ID to compare */ doc_id_t cmp_doc_id, /*!< in: Doc ID to compare */
ibool read_only, /*!< in: TRUE if read the ibool read_only, /*!< in: TRUE if read the
synced_doc_id only */ synced_doc_id only */
doc_id_t* doc_id) /*!< out: larger document id doc_id_t* doc_id) /*!< out: larger document id
after comparing "doc_id_cmp" after comparing "cmp_doc_id"
to the one stored in CONFIG to the one stored in CONFIG
table */ table */
{ {
@ -2667,10 +2667,10 @@ retry:
goto func_exit; goto func_exit;
} }
if (doc_id_cmp == 0 && *doc_id) { if (cmp_doc_id == 0 && *doc_id) {
cache->synced_doc_id = *doc_id - 1; cache->synced_doc_id = *doc_id - 1;
} else { } else {
cache->synced_doc_id = ut_max(doc_id_cmp, *doc_id); cache->synced_doc_id = ut_max(cmp_doc_id, *doc_id);
} }
mutex_enter(&cache->doc_id_lock); mutex_enter(&cache->doc_id_lock);
@ -2681,7 +2681,7 @@ retry:
} }
mutex_exit(&cache->doc_id_lock); mutex_exit(&cache->doc_id_lock);
if (doc_id_cmp > *doc_id) { if (cmp_doc_id > *doc_id) {
error = fts_update_sync_doc_id( error = fts_update_sync_doc_id(
table, cache->synced_doc_id, trx); table, cache->synced_doc_id, trx);
} }
@ -2803,7 +2803,7 @@ fts_doc_ids_create(void)
fts_doc_ids->self_heap = ib_heap_allocator_create(heap); fts_doc_ids->self_heap = ib_heap_allocator_create(heap);
fts_doc_ids->doc_ids = static_cast<ib_vector_t*>(ib_vector_create( fts_doc_ids->doc_ids = static_cast<ib_vector_t*>(ib_vector_create(
fts_doc_ids->self_heap, sizeof(fts_update_t), 32)); fts_doc_ids->self_heap, sizeof(doc_id_t), 32));
return(fts_doc_ids); return(fts_doc_ids);
} }
@ -3878,7 +3878,7 @@ fts_sync_add_deleted_cache(
ut_a(ib_vector_size(doc_ids) > 0); ut_a(ib_vector_size(doc_ids) > 0);
ib_vector_sort(doc_ids, fts_update_doc_id_cmp); ib_vector_sort(doc_ids, fts_doc_id_cmp);
info = pars_info_create(); info = pars_info_create();
@ -3896,13 +3896,13 @@ fts_sync_add_deleted_cache(
"BEGIN INSERT INTO $table_name VALUES (:doc_id);"); "BEGIN INSERT INTO $table_name VALUES (:doc_id);");
for (i = 0; i < n_elems && error == DB_SUCCESS; ++i) { for (i = 0; i < n_elems && error == DB_SUCCESS; ++i) {
fts_update_t* update; doc_id_t* update;
doc_id_t write_doc_id; doc_id_t write_doc_id;
update = static_cast<fts_update_t*>(ib_vector_get(doc_ids, i)); update = static_cast<doc_id_t*>(ib_vector_get(doc_ids, i));
/* Convert to "storage" byte order. */ /* Convert to "storage" byte order. */
fts_write_doc_id((byte*) &write_doc_id, update->doc_id); fts_write_doc_id((byte*) &write_doc_id, *update);
fts_bind_doc_id(info, "doc_id", &write_doc_id); fts_bind_doc_id(info, "doc_id", &write_doc_id);
error = fts_eval_sql(sync->trx, graph); error = fts_eval_sql(sync->trx, graph);
@ -5193,12 +5193,12 @@ fts_cache_append_deleted_doc_ids(
for (ulint i = 0; i < ib_vector_size(cache->deleted_doc_ids); ++i) { for (ulint i = 0; i < ib_vector_size(cache->deleted_doc_ids); ++i) {
fts_update_t* update; doc_id_t* update;
update = static_cast<fts_update_t*>( update = static_cast<doc_id_t*>(
ib_vector_get(cache->deleted_doc_ids, i)); ib_vector_get(cache->deleted_doc_ids, i));
ib_vector_push(vector, &update->doc_id); ib_vector_push(vector, &update);
} }
mutex_exit((ib_mutex_t*) &cache->deleted_lock); mutex_exit((ib_mutex_t*) &cache->deleted_lock);

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2019, MariaDB Corporation. Copyright (c) 2016, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -925,7 +925,7 @@ fts_fetch_doc_ids(
int i = 0; int i = 0;
sel_node_t* sel_node = static_cast<sel_node_t*>(row); sel_node_t* sel_node = static_cast<sel_node_t*>(row);
fts_doc_ids_t* fts_doc_ids = static_cast<fts_doc_ids_t*>(user_arg); fts_doc_ids_t* fts_doc_ids = static_cast<fts_doc_ids_t*>(user_arg);
fts_update_t* update = static_cast<fts_update_t*>( doc_id_t* update = static_cast<doc_id_t*>(
ib_vector_push(fts_doc_ids->doc_ids, NULL)); ib_vector_push(fts_doc_ids->doc_ids, NULL));
for (exp = sel_node->select_list; for (exp = sel_node->select_list;
@ -941,8 +941,7 @@ fts_fetch_doc_ids(
/* Note: The column numbers below must match the SELECT. */ /* Note: The column numbers below must match the SELECT. */
switch (i) { switch (i) {
case 0: /* DOC_ID */ case 0: /* DOC_ID */
update->fts_indexes = NULL; *update = fts_read_doc_id(
update->doc_id = fts_read_doc_id(
static_cast<byte*>(data)); static_cast<byte*>(data));
break; break;
@ -1010,7 +1009,7 @@ fts_table_fetch_doc_ids(
mutex_exit(&dict_sys.mutex); mutex_exit(&dict_sys.mutex);
if (error == DB_SUCCESS) { if (error == DB_SUCCESS) {
ib_vector_sort(doc_ids->doc_ids, fts_update_doc_id_cmp); ib_vector_sort(doc_ids->doc_ids, fts_doc_id_cmp);
} }
if (alloc_bk_trx) { if (alloc_bk_trx) {
@ -1027,7 +1026,7 @@ Do a binary search for a doc id in the array
int int
fts_bsearch( fts_bsearch(
/*========*/ /*========*/
fts_update_t* array, /*!< in: array to sort */ doc_id_t* array, /*!< in: array to sort */
int lower, /*!< in: the array lower bound */ int lower, /*!< in: the array lower bound */
int upper, /*!< in: the array upper bound */ int upper, /*!< in: the array upper bound */
doc_id_t doc_id) /*!< in: the doc id to search for */ doc_id_t doc_id) /*!< in: the doc id to search for */
@ -1041,9 +1040,9 @@ fts_bsearch(
while (lower < upper) { while (lower < upper) {
int i = (lower + upper) >> 1; int i = (lower + upper) >> 1;
if (doc_id > array[i].doc_id) { if (doc_id > array[i]) {
lower = i + 1; lower = i + 1;
} else if (doc_id < array[i].doc_id) { } else if (doc_id < array[i]) {
upper = i - 1; upper = i - 1;
} else { } else {
return(i); /* Found. */ return(i); /* Found. */
@ -1052,7 +1051,7 @@ fts_bsearch(
} }
if (lower == upper && lower < orig_size) { if (lower == upper && lower < orig_size) {
if (doc_id == array[lower].doc_id) { if (doc_id == array[lower]) {
return(lower); return(lower);
} else if (lower == 0) { } else if (lower == 0) {
return(-1); return(-1);
@ -1079,7 +1078,7 @@ fts_optimize_lookup(
{ {
int pos; int pos;
int upper = static_cast<int>(ib_vector_size(doc_ids)); int upper = static_cast<int>(ib_vector_size(doc_ids));
fts_update_t* array = (fts_update_t*) doc_ids->data; doc_id_t* array = (doc_id_t*) doc_ids->data;
pos = fts_bsearch(array, static_cast<int>(lower), upper, first_doc_id); pos = fts_bsearch(array, static_cast<int>(lower), upper, first_doc_id);
@ -1092,10 +1091,10 @@ fts_optimize_lookup(
/* If i is 1, it could be first_doc_id is less than /* If i is 1, it could be first_doc_id is less than
either the first or second array item, do a either the first or second array item, do a
double check */ double check */
if (i == 1 && array[0].doc_id <= last_doc_id if (i == 1 && array[0] <= last_doc_id
&& first_doc_id < array[0].doc_id) { && first_doc_id < array[0]) {
pos = 0; pos = 0;
} else if (i < upper && array[i].doc_id <= last_doc_id) { } else if (i < upper && array[i] <= last_doc_id) {
/* Check if the "next" doc id is within the /* Check if the "next" doc id is within the
first & last doc id of the node. */ first & last doc id of the node. */
@ -1234,12 +1233,12 @@ test_again:
delta for decoding the entries following this document's delta for decoding the entries following this document's
entries. */ entries. */
if (*del_pos >= 0 && *del_pos < (int) ib_vector_size(del_vec)) { if (*del_pos >= 0 && *del_pos < (int) ib_vector_size(del_vec)) {
fts_update_t* update; doc_id_t* update;
update = (fts_update_t*) ib_vector_get( update = (doc_id_t*) ib_vector_get(
del_vec, ulint(*del_pos)); del_vec, ulint(*del_pos));
del_doc_id = update->doc_id; del_doc_id = *update;
} }
if (enc->src_ilist_ptr == src_node->ilist && doc_id == 0) { if (enc->src_ilist_ptr == src_node->ilist && doc_id == 0) {
@ -2025,7 +2024,7 @@ fts_optimize_purge_deleted_doc_ids(
ulint i; ulint i;
pars_info_t* info; pars_info_t* info;
que_t* graph; que_t* graph;
fts_update_t* update; doc_id_t* update;
doc_id_t write_doc_id; doc_id_t write_doc_id;
dberr_t error = DB_SUCCESS; dberr_t error = DB_SUCCESS;
char deleted[MAX_FULL_NAME_LEN]; char deleted[MAX_FULL_NAME_LEN];
@ -2035,11 +2034,11 @@ fts_optimize_purge_deleted_doc_ids(
ut_a(ib_vector_size(optim->to_delete->doc_ids) > 0); ut_a(ib_vector_size(optim->to_delete->doc_ids) > 0);
update = static_cast<fts_update_t*>( update = static_cast<doc_id_t*>(
ib_vector_get(optim->to_delete->doc_ids, 0)); ib_vector_get(optim->to_delete->doc_ids, 0));
/* Convert to "storage" byte order. */ /* Convert to "storage" byte order. */
fts_write_doc_id((byte*) &write_doc_id, update->doc_id); fts_write_doc_id((byte*) &write_doc_id, *update);
/* This is required for the SQL parser to work. It must be able /* This is required for the SQL parser to work. It must be able
to find the following variables. So we do it twice. */ to find the following variables. So we do it twice. */
@ -2061,11 +2060,11 @@ fts_optimize_purge_deleted_doc_ids(
/* Delete the doc ids that were copied at the start. */ /* Delete the doc ids that were copied at the start. */
for (i = 0; i < ib_vector_size(optim->to_delete->doc_ids); ++i) { for (i = 0; i < ib_vector_size(optim->to_delete->doc_ids); ++i) {
update = static_cast<fts_update_t*>(ib_vector_get( update = static_cast<doc_id_t*>(ib_vector_get(
optim->to_delete->doc_ids, i)); optim->to_delete->doc_ids, i));
/* Convert to "storage" byte order. */ /* Convert to "storage" byte order. */
fts_write_doc_id((byte*) &write_doc_id, update->doc_id); fts_write_doc_id((byte*) &write_doc_id, *update);
fts_bind_doc_id(info, "doc_id1", &write_doc_id); fts_bind_doc_id(info, "doc_id1", &write_doc_id);

View File

@ -731,10 +731,10 @@ fts_query_union_doc_id(
{ {
ib_rbt_bound_t parent; ib_rbt_bound_t parent;
ulint size = ib_vector_size(query->deleted->doc_ids); ulint size = ib_vector_size(query->deleted->doc_ids);
fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data;
/* Check if the doc id is deleted and it's not already in our set. */ /* Check if the doc id is deleted and it's not already in our set. */
if (fts_bsearch(array, 0, static_cast<int>(size), doc_id) < 0 if (fts_bsearch(updates, 0, static_cast<int>(size), doc_id) < 0
&& rbt_search(query->doc_ids, &parent, &doc_id) != 0) { && rbt_search(query->doc_ids, &parent, &doc_id) != 0) {
fts_ranking_t ranking; fts_ranking_t ranking;
@ -762,10 +762,10 @@ fts_query_remove_doc_id(
{ {
ib_rbt_bound_t parent; ib_rbt_bound_t parent;
ulint size = ib_vector_size(query->deleted->doc_ids); ulint size = ib_vector_size(query->deleted->doc_ids);
fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data;
/* Check if the doc id is deleted and it's in our set. */ /* Check if the doc id is deleted and it's in our set. */
if (fts_bsearch(array, 0, static_cast<int>(size), doc_id) < 0 if (fts_bsearch(updates, 0, static_cast<int>(size), doc_id) < 0
&& rbt_search(query->doc_ids, &parent, &doc_id) == 0) { && rbt_search(query->doc_ids, &parent, &doc_id) == 0) {
ut_free(rbt_remove_node(query->doc_ids, parent.last)); ut_free(rbt_remove_node(query->doc_ids, parent.last));
@ -792,10 +792,10 @@ fts_query_change_ranking(
{ {
ib_rbt_bound_t parent; ib_rbt_bound_t parent;
ulint size = ib_vector_size(query->deleted->doc_ids); ulint size = ib_vector_size(query->deleted->doc_ids);
fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data;
/* Check if the doc id is deleted and it's in our set. */ /* Check if the doc id is deleted and it's in our set. */
if (fts_bsearch(array, 0, static_cast<int>(size), doc_id) < 0 if (fts_bsearch(updates, 0, static_cast<int>(size), doc_id) < 0
&& rbt_search(query->doc_ids, &parent, &doc_id) == 0) { && rbt_search(query->doc_ids, &parent, &doc_id) == 0) {
fts_ranking_t* ranking; fts_ranking_t* ranking;
@ -829,7 +829,7 @@ fts_query_intersect_doc_id(
{ {
ib_rbt_bound_t parent; ib_rbt_bound_t parent;
ulint size = ib_vector_size(query->deleted->doc_ids); ulint size = ib_vector_size(query->deleted->doc_ids);
fts_update_t* array = (fts_update_t*) query->deleted->doc_ids->data; doc_id_t* updates = (doc_id_t*) query->deleted->doc_ids->data;
fts_ranking_t* ranking= NULL; fts_ranking_t* ranking= NULL;
/* There are three types of intersect: /* There are three types of intersect:
@ -841,7 +841,7 @@ fts_query_intersect_doc_id(
if it matches 'b' and it's in doc_ids.(multi_exist = true). */ if it matches 'b' and it's in doc_ids.(multi_exist = true). */
/* Check if the doc id is deleted and it's in our set */ /* Check if the doc id is deleted and it's in our set */
if (fts_bsearch(array, 0, static_cast<int>(size), doc_id) < 0) { if (fts_bsearch(updates, 0, static_cast<int>(size), doc_id) < 0) {
fts_ranking_t new_ranking; fts_ranking_t new_ranking;
if (rbt_search(query->doc_ids, &parent, &doc_id) != 0) { if (rbt_search(query->doc_ids, &parent, &doc_id) != 0) {
@ -3651,8 +3651,8 @@ fts_query_prepare_result(
if (query->flags == FTS_OPT_RANKING) { if (query->flags == FTS_OPT_RANKING) {
fts_word_freq_t* word_freq; fts_word_freq_t* word_freq;
ulint size = ib_vector_size(query->deleted->doc_ids); ulint size = ib_vector_size(query->deleted->doc_ids);
fts_update_t* array = doc_id_t* updates =
(fts_update_t*) query->deleted->doc_ids->data; (doc_id_t*) query->deleted->doc_ids->data;
node = rbt_first(query->word_freqs); node = rbt_first(query->word_freqs);
ut_ad(node); ut_ad(node);
@ -3667,7 +3667,7 @@ fts_query_prepare_result(
doc_freq = rbt_value(fts_doc_freq_t, node); doc_freq = rbt_value(fts_doc_freq_t, node);
/* Don't put deleted docs into result */ /* Don't put deleted docs into result */
if (fts_bsearch(array, 0, static_cast<int>(size), if (fts_bsearch(updates, 0, static_cast<int>(size),
doc_freq->doc_id) >= 0) { doc_freq->doc_id) >= 0) {
/* one less matching doc count */ /* one less matching doc count */
--word_freq->doc_count; --word_freq->doc_count;
@ -4018,7 +4018,7 @@ fts_query(
DEBUG_SYNC_C("fts_deleted_doc_ids_append"); DEBUG_SYNC_C("fts_deleted_doc_ids_append");
/* Sort the vector so that we can do a binary search over the ids. */ /* Sort the vector so that we can do a binary search over the ids. */
ib_vector_sort(query.deleted->doc_ids, fts_update_doc_id_cmp); ib_vector_sort(query.deleted->doc_ids, fts_doc_id_cmp);
/* Convert the query string to lower case before parsing. We own /* Convert the query string to lower case before parsing. We own
the ut_malloc'ed result and so remember to free it before return. */ the ut_malloc'ed result and so remember to free it before return. */

View File

@ -20141,7 +20141,7 @@ static MYSQL_SYSVAR_UINT(encryption_threads, srv_n_fil_crypt_threads,
"Number of threads performing background key rotation ", "Number of threads performing background key rotation ",
NULL, NULL,
innodb_encryption_threads_update, innodb_encryption_threads_update,
srv_n_fil_crypt_threads, 0, UINT_MAX32, 0); 0, 0, 255, 0);
static MYSQL_SYSVAR_UINT(encryption_rotate_key_age, static MYSQL_SYSVAR_UINT(encryption_rotate_key_age,
srv_fil_crypt_rotate_key_age, srv_fil_crypt_rotate_key_age,

View File

@ -1018,16 +1018,12 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
@return whether the table will be rebuilt */ @return whether the table will be rebuilt */
bool need_rebuild () const { return(old_table != new_table); } bool need_rebuild () const { return(old_table != new_table); }
/** Clear uncommmitted added indexes after a failed operation. */ /** Clear uncommmitted added indexes after a failed operation. */
void clear_added_indexes() void clear_added_indexes()
{ {
for (ulint i = 0; i < num_to_add_index; i++) { for (ulint i= 0; i < num_to_add_index; i++)
if (!add_index[i]->is_committed()) { add_index[i]->detach_columns(true);
add_index[i]->detach_columns(); }
add_index[i]->n_fields = 0;
}
}
}
/** Convert table-rebuilding ALTER to instant ALTER. */ /** Convert table-rebuilding ALTER to instant ALTER. */
void prepare_instant() void prepare_instant()
@ -6190,6 +6186,7 @@ prepare_inplace_alter_table_dict(
create_table_info_t info(ctx->prebuilt->trx->mysql_thd, altered_table, create_table_info_t info(ctx->prebuilt->trx->mysql_thd, altered_table,
ha_alter_info->create_info, NULL, NULL, ha_alter_info->create_info, NULL, NULL,
srv_file_per_table); srv_file_per_table);
ut_d(bool stats_wait = false);
/* The primary index would be rebuilt if a FTS Doc ID /* The primary index would be rebuilt if a FTS Doc ID
column is to be added, and the primary index definition column is to be added, and the primary index definition
@ -6241,6 +6238,7 @@ prepare_inplace_alter_table_dict(
XXX what may happen if bg stats opens the table after we XXX what may happen if bg stats opens the table after we
have unlocked data dictionary below? */ have unlocked data dictionary below? */
dict_stats_wait_bg_to_stop_using_table(user_table, ctx->trx); dict_stats_wait_bg_to_stop_using_table(user_table, ctx->trx);
ut_d(stats_wait = true);
online_retry_drop_indexes_low(ctx->new_table, ctx->trx); online_retry_drop_indexes_low(ctx->new_table, ctx->trx);
@ -7123,7 +7121,8 @@ error_handled:
/* n_ref_count must be 1, because purge cannot /* n_ref_count must be 1, because purge cannot
be executing on this very table as we are be executing on this very table as we are
holding dict_sys.latch X-latch. */ holding dict_sys.latch X-latch. */
DBUG_ASSERT(user_table->get_ref_count() == 1 || ctx->online); ut_ad(!stats_wait || ctx->online
|| user_table->get_ref_count() == 1);
online_retry_drop_indexes_with_trx(user_table, ctx->trx); online_retry_drop_indexes_with_trx(user_table, ctx->trx);
} else { } else {

View File

@ -579,101 +579,103 @@ private:
static const unsigned DROPPED = 1023; static const unsigned DROPPED = 1023;
public: public:
/** Detach the column from an index. /** Detach a virtual column from an index.
@param[in] index index to be detached from */ @param index being-freed index */
inline void detach(const dict_index_t& index); inline void detach(const dict_index_t &index);
/** Data for instantly added columns */ /** Data for instantly added columns */
struct def_t { struct def_t
/** original default value of instantly added column */ {
const void* data; /** original default value of instantly added column */
/** len of data, or UNIV_SQL_DEFAULT if unavailable */ const void *data;
ulint len; /** len of data, or UNIV_SQL_DEFAULT if unavailable */
} def_val; ulint len;
} def_val;
/** Retrieve the column name. /** Retrieve the column name.
@param[in] table the table of this column */ @param table the table of this column */
const char* name(const dict_table_t& table) const; const char *name(const dict_table_t &table) const;
/** @return whether this is a virtual column */ /** @return whether this is a virtual column */
bool is_virtual() const { return prtype & DATA_VIRTUAL; } bool is_virtual() const { return prtype & DATA_VIRTUAL; }
/** @return whether NULL is an allowed value for this column */ /** @return whether NULL is an allowed value for this column */
bool is_nullable() const { return !(prtype & DATA_NOT_NULL); } bool is_nullable() const { return !(prtype & DATA_NOT_NULL); }
/** @return whether table of this system field is TRX_ID-based */ /** @return whether table of this system field is TRX_ID-based */
bool vers_native() const bool vers_native() const
{ {
ut_ad(vers_sys_start() || vers_sys_end()); ut_ad(vers_sys_start() || vers_sys_end());
ut_ad(mtype == DATA_INT || mtype == DATA_FIXBINARY); ut_ad(mtype == DATA_INT || mtype == DATA_FIXBINARY);
return mtype == DATA_INT; return mtype == DATA_INT;
} }
/** @return whether this user column (not row_start, row_end) /** @return whether this user column (not row_start, row_end)
has System Versioning property */ has System Versioning property */
bool is_versioned() const { return !(~prtype & DATA_VERSIONED); } bool is_versioned() const { return !(~prtype & DATA_VERSIONED); }
/** @return whether this is the system version start */ /** @return whether this is the system version start */
bool vers_sys_start() const bool vers_sys_start() const
{ {
return (prtype & DATA_VERSIONED) == DATA_VERS_START; return (prtype & DATA_VERSIONED) == DATA_VERS_START;
} }
/** @return whether this is the system version end */ /** @return whether this is the system version end */
bool vers_sys_end() const bool vers_sys_end() const
{ {
return (prtype & DATA_VERSIONED) == DATA_VERS_END; return (prtype & DATA_VERSIONED) == DATA_VERS_END;
} }
/** @return whether this is an instantly-added column */ /** @return whether this is an instantly-added column */
bool is_added() const bool is_added() const
{ {
DBUG_ASSERT(def_val.len != UNIV_SQL_DEFAULT || !def_val.data); DBUG_ASSERT(def_val.len != UNIV_SQL_DEFAULT || !def_val.data);
return def_val.len != UNIV_SQL_DEFAULT; return def_val.len != UNIV_SQL_DEFAULT;
} }
/** Flag the column instantly dropped */ /** Flag the column instantly dropped */
void set_dropped() { ind = DROPPED; } void set_dropped() { ind = DROPPED; }
/** Flag the column instantly dropped. /** Flag the column instantly dropped.
@param[in] not_null whether the column was NOT NULL @param not_null whether the column was NOT NULL
@param[in] len2 whether the length exceeds 255 bytes @param len2 whether the length exceeds 255 bytes
@param[in] fixed_len the fixed length in bytes, or 0 */ @param fixed_len the fixed length in bytes, or 0 */
void set_dropped(bool not_null, bool len2, unsigned fixed) void set_dropped(bool not_null, bool len2, unsigned fixed)
{ {
DBUG_ASSERT(!len2 || !fixed); DBUG_ASSERT(!len2 || !fixed);
prtype = not_null prtype= not_null ? DATA_NOT_NULL | DATA_BINARY_TYPE : DATA_BINARY_TYPE;
? DATA_NOT_NULL | DATA_BINARY_TYPE if (fixed)
: DATA_BINARY_TYPE; {
if (fixed) { mtype= DATA_FIXBINARY;
mtype = DATA_FIXBINARY; len= static_cast<uint16_t>(fixed);
len = static_cast<uint16_t>(fixed); }
} else { else
mtype = DATA_BINARY; {
len = len2 ? 65535 : 255; mtype= DATA_BINARY;
} len= len2 ? 65535 : 255;
mbminlen = mbmaxlen = 0; }
ind = DROPPED; mbminlen= mbmaxlen= 0;
ord_part = 0; ind= DROPPED;
max_prefix = 0; ord_part= 0;
} max_prefix= 0;
/** @return whether the column was instantly dropped */ }
bool is_dropped() const { return ind == DROPPED; } /** @return whether the column was instantly dropped */
/** @return whether the column was instantly dropped bool is_dropped() const { return ind == DROPPED; }
@param[in] index the clustered index */ /** @return whether the column was instantly dropped
inline bool is_dropped(const dict_index_t& index) const; @param index the clustered index */
inline bool is_dropped(const dict_index_t &index) const;
/** Get the default value of an instantly-added column. /** Get the default value of an instantly-added column.
@param[out] len value length (in bytes), or UNIV_SQL_NULL @param[out] len value length (in bytes), or UNIV_SQL_NULL
@return default value @return default value
@retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */ @retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */
const byte* instant_value(ulint* len) const const byte *instant_value(ulint *len) const
{ {
DBUG_ASSERT(is_added()); DBUG_ASSERT(is_added());
*len = def_val.len; *len= def_val.len;
return static_cast<const byte*>(def_val.data); return static_cast<const byte*>(def_val.data);
} }
/** Remove the 'instant ADD' status of the column */ /** Remove the 'instant ADD' status of the column */
void clear_instant() void clear_instant()
{ {
def_val.len = UNIV_SQL_DEFAULT; def_val.len= UNIV_SQL_DEFAULT;
def_val.data = NULL; def_val.data= NULL;
} }
/** @return whether two columns have compatible data type encoding */ /** @return whether two columns have compatible data type encoding */
bool same_type(const dict_col_t &other) const bool same_type(const dict_col_t &other) const
@ -719,24 +721,21 @@ public:
/** @return whether two collations codes have the same character encoding */ /** @return whether two collations codes have the same character encoding */
static bool same_encoding(uint16_t a, uint16_t b); static bool same_encoding(uint16_t a, uint16_t b);
/** Determine if the columns have the same format /** Determine if the columns have the same format
except for is_nullable() and is_versioned(). except for is_nullable() and is_versioned().
@param[in] other column to compare to @param other column to compare to
@return whether the columns have the same format */ @return whether the columns have the same format */
bool same_format(const dict_col_t& other) const bool same_format(const dict_col_t &other) const
{ {
return same_type(other) return same_type(other) && len >= other.len &&
&& len >= other.len mbminlen == other.mbminlen && mbmaxlen == other.mbmaxlen &&
&& mbminlen == other.mbminlen !((prtype ^ other.prtype) & ~(DATA_NOT_NULL | DATA_VERSIONED |
&& mbmaxlen == other.mbmaxlen CHAR_COLL_MASK << 16 |
&& !((prtype ^ other.prtype) DATA_LONG_TRUE_VARCHAR));
& ~(DATA_NOT_NULL | DATA_VERSIONED }
| CHAR_COLL_MASK << 16
| DATA_LONG_TRUE_VARCHAR));
}
/** @return whether the column values are comparable by memcmp() */ /** @return whether the column values are comparable by memcmp() */
inline bool is_binary() const { return prtype & DATA_BINARY_TYPE; } bool is_binary() const { return prtype & DATA_BINARY_TYPE; }
}; };
/** Index information put in a list of virtual column structure. Index /** Index information put in a list of virtual column structure. Index
@ -774,27 +773,30 @@ struct dict_v_col_t{
std::forward_list<dict_v_idx_t, ut_allocator<dict_v_idx_t> > std::forward_list<dict_v_idx_t, ut_allocator<dict_v_idx_t> >
v_indexes; v_indexes;
/** Detach the column from an index. /** Detach the column from an index.
@param[in] index index to be detached from */ @param index index to be detached from */
void detach(const dict_index_t& index) void detach(const dict_index_t &index)
{ {
if (!n_v_indexes) return; if (!n_v_indexes) return;
auto i = v_indexes.before_begin(); auto i= v_indexes.before_begin();
ut_d(unsigned n = 0); ut_d(unsigned n= 0);
do { do {
auto prev = i++; auto prev = i++;
if (i == v_indexes.end()) { if (i == v_indexes.end())
ut_ad(n == n_v_indexes); {
return; ut_ad(n == n_v_indexes);
} return;
ut_ad(++n <= n_v_indexes); }
if (i->index == &index) { ut_ad(++n <= n_v_indexes);
v_indexes.erase_after(prev); if (i->index == &index)
n_v_indexes--; {
return; v_indexes.erase_after(prev);
} n_v_indexes--;
} while (i != v_indexes.end()); return;
} }
}
while (i != v_indexes.end());
}
}; };
/** Data structure for newly added virtual column in a table */ /** Data structure for newly added virtual column in a table */
@ -1204,15 +1206,22 @@ public:
/** @return whether the index is corrupted */ /** @return whether the index is corrupted */
inline bool is_corrupted() const; inline bool is_corrupted() const;
/** Detach the columns from the index that is to be freed. */ /** Detach the virtual columns from the index that is to be removed.
void detach_columns() @param whether to reset fields[].col */
{ void detach_columns(bool clear= false)
if (has_virtual()) { {
for (unsigned i = 0; i < n_fields; i++) { if (!has_virtual())
fields[i].col->detach(*this); return;
} for (unsigned i= 0; i < n_fields; i++)
} {
} dict_col_t* col= fields[i].col;
if (!col || !col->is_virtual())
continue;
col->detach(*this);
if (clear)
fields[i].col= nullptr;
}
}
/** Determine how many fields of a given prefix can be set NULL. /** Determine how many fields of a given prefix can be set NULL.
@param[in] n_prefix number of fields in the prefix @param[in] n_prefix number of fields in the prefix
@ -1358,13 +1367,12 @@ public:
inline record_size_info_t record_size_info() const; inline record_size_info_t record_size_info() const;
}; };
/** Detach a column from an index. /** Detach a virtual column from an index.
@param[in] index index to be detached from */ @param index being-freed index */
inline void dict_col_t::detach(const dict_index_t& index) inline void dict_col_t::detach(const dict_index_t &index)
{ {
if (is_virtual()) { if (is_virtual())
reinterpret_cast<dict_v_col_t*>(this)->detach(index); reinterpret_cast<dict_v_col_t*>(this)->detach(index);
}
} }
/** The status of online index creation */ /** The status of online index creation */

View File

@ -239,7 +239,7 @@ Do a binary search for a doc id in the array
int int
fts_bsearch( fts_bsearch(
/*========*/ /*========*/
fts_update_t* array, /*!< in: array to sort */ doc_id_t* array, /*!< in: array to sort */
int lower, /*!< in: lower bound of array*/ int lower, /*!< in: lower bound of array*/
int upper, /*!< in: upper bound of array*/ int upper, /*!< in: upper bound of array*/
doc_id_t doc_id) /*!< in: doc id to lookup */ doc_id_t doc_id) /*!< in: doc id to lookup */

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2019, MariaDB Corporation. Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under 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 the terms of the GNU General Public License as published by the Free Software
@ -80,20 +80,6 @@ struct fts_index_cache_t {
CHARSET_INFO* charset; /*!< charset */ CHARSET_INFO* charset; /*!< charset */
}; };
/** For supporting the tracking of updates on multiple FTS indexes we need
to track which FTS indexes need to be updated. For INSERT and DELETE we
update all fts indexes. */
struct fts_update_t {
doc_id_t doc_id; /*!< The doc id affected */
ib_vector_t* fts_indexes; /*!< The FTS indexes that need to be
updated. A NULL value means all
indexes need to be updated. This
vector is not allocated on the heap
and so must be freed explicitly,
when we are done with it */
};
/** Stop word control infotmation. */ /** Stop word control infotmation. */
struct fts_stopword_t { struct fts_stopword_t {
ulint status; /*!< Status of the stopword tree */ ulint status; /*!< Status of the stopword tree */
@ -319,10 +305,9 @@ fts_ranking_doc_id_cmp(
const void* p2); /*!< in: id2 */ const void* p2); /*!< in: id2 */
/******************************************************************//** /******************************************************************//**
Compare two fts_update_t instances doc_ids. */ Compare two doc_ids. */
UNIV_INLINE UNIV_INLINE
int int fts_doc_id_cmp(
fts_update_doc_id_cmp(
/*==================*/ /*==================*/
/*!< out: /*!< out:
< 0 if n1 < n2, < 0 if n1 < n2,

View File

@ -79,19 +79,18 @@ fts_ranking_doc_id_cmp(
} }
/******************************************************************//** /******************************************************************//**
Compare two fts_update_t doc_ids. Compare two doc_ids.
@return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */ @return < 0 if n1 < n2, 0 if n1 == n2, > 0 if n1 > n2 */
UNIV_INLINE UNIV_INLINE
int int fts_doc_id_cmp(
fts_update_doc_id_cmp(
/*==================*/ /*==================*/
const void* p1, /*!< in: id1 */ const void* p1, /*!< in: id1 */
const void* p2) /*!< in: id2 */ const void* p2) /*!< in: id2 */
{ {
const fts_update_t* up1 = (const fts_update_t*) p1; const doc_id_t* up1 = static_cast<const doc_id_t*>(p1);
const fts_update_t* up2 = (const fts_update_t*) p2; const doc_id_t* up2 = static_cast<const doc_id_t*>(p2);
return((int)(up1->doc_id - up2->doc_id)); return static_cast<int>(*up1 - *up2);
} }
/******************************************************************//** /******************************************************************//**

View File

@ -411,6 +411,14 @@ class error : public logger {
public: public:
ATTRIBUTE_COLD ATTRIBUTE_COLD
~error(); ~error();
/** Indicates that error::~error() was invoked. Can be used to
determine if error messages were logged during innodb code execution.
@return true if there were error messages, false otherwise. */
static bool was_logged() { return logged; }
private:
/** true if error::~error() was invoked, false otherwise */
static bool logged;
}; };
/** The class fatal is used to emit an error message and stop the server /** The class fatal is used to emit an error message and stop the server

View File

@ -6207,7 +6207,7 @@ static my_bool lock_table_locks_lookup(rw_trx_hash_element_t *element,
ut_ad(lock->trx == element->trx); ut_ad(lock->trx == element->trx);
if (lock_get_type_low(lock) == LOCK_REC) if (lock_get_type_low(lock) == LOCK_REC)
{ {
ut_ad(!dict_index_is_online_ddl(lock->index) || ut_ad(lock->index->online_status != ONLINE_INDEX_CREATION ||
lock->index->is_primary()); lock->index->is_primary());
ut_ad(lock->index->table != table); ut_ad(lock->index->table != table);
} }

View File

@ -4005,7 +4005,7 @@ static bool is_linux_native_aio_supported()
case -EINVAL: case -EINVAL:
case -ENOSYS: case -ENOSYS:
ib::error() ib::warn()
<< "Linux Native AIO not supported. You can either" << "Linux Native AIO not supported. You can either"
" move " " move "
<< (srv_read_only_mode ? log_file_path : "tmpdir") << (srv_read_only_mode ? log_file_path : "tmpdir")
@ -4015,7 +4015,7 @@ static bool is_linux_native_aio_supported()
/* fall through. */ /* fall through. */
default: default:
ib::error() ib::warn()
<< "Linux Native AIO check on " << "Linux Native AIO check on "
<< (srv_read_only_mode ? log_file_path : "tmpdir") << (srv_read_only_mode ? log_file_path : "tmpdir")
<< "returned error[" << -err << "]"; << "returned error[" << -err << "]";

View File

@ -58,35 +58,22 @@ check.
If you make a change in this module make sure that no codepath is If you make a change in this module make sure that no codepath is
introduced where a call to log_free_check() is bypassed. */ introduced where a call to log_free_check() is bypassed. */
/***********************************************************//** /** Create an row template for each index of a table. */
Creates an entry template for each index of a table. */ static void ins_node_create_entry_list(ins_node_t *node)
static
void
ins_node_create_entry_list(
/*=======================*/
ins_node_t* node) /*!< in: row insert node */
{ {
dict_index_t* index; node->entry_list.reserve(UT_LIST_GET_LEN(node->table->indexes));
dtuple_t* entry;
ut_ad(node->entry_sys_heap); for (dict_index_t *index= dict_table_get_first_index(node->table); index;
index= dict_table_get_next_index(index))
/* We will include all indexes (include those corrupted {
secondary indexes) in the entry list. Filtration of /* Corrupted or incomplete secondary indexes will be filtered out in
these corrupted index will be done in row_ins() */ row_ins(). */
dtuple_t *entry= index->online_status >= ONLINE_INDEX_ABORTED
node->entry_list.reserve(UT_LIST_GET_LEN(node->table->indexes)); ? dtuple_create(node->entry_sys_heap, 0)
: row_build_index_entry_low(node->row, NULL, index, node->entry_sys_heap,
for (index = dict_table_get_first_index(node->table); ROW_BUILD_FOR_INSERT);
index != 0; node->entry_list.push_back(entry);
index = dict_table_get_next_index(index)) { }
entry = row_build_index_entry_low(
node->row, NULL, index, node->entry_sys_heap,
ROW_BUILD_FOR_INSERT);
node->entry_list.push_back(entry);
}
} }
/*****************************************************************//** /*****************************************************************//**

View File

@ -1280,10 +1280,6 @@ void
row_sel_open_pcur( row_sel_open_pcur(
/*==============*/ /*==============*/
plan_t* plan, /*!< in: table plan */ plan_t* plan, /*!< in: table plan */
#ifdef BTR_CUR_HASH_ADAPT
rw_lock_t* ahi_latch,
/*!< in: the adaptive hash index latch */
#endif /* BTR_CUR_HASH_ADAPT */
mtr_t* mtr) /*!< in/out: mini-transaction */ mtr_t* mtr) /*!< in/out: mini-transaction */
{ {
dict_index_t* index; dict_index_t* index;
@ -1327,7 +1323,7 @@ row_sel_open_pcur(
btr_pcur_open_with_no_init(index, plan->tuple, plan->mode, btr_pcur_open_with_no_init(index, plan->tuple, plan->mode,
BTR_SEARCH_LEAF, &plan->pcur, BTR_SEARCH_LEAF, &plan->pcur,
ahi_latch, mtr); NULL, mtr);
} else { } else {
/* Open the cursor to the start or the end of the index /* Open the cursor to the start or the end of the index
(FALSE: no init) */ (FALSE: no init) */
@ -1472,16 +1468,12 @@ row_sel_try_search_shortcut(
ut_ad(plan->unique_search); ut_ad(plan->unique_search);
ut_ad(!plan->must_get_clust); ut_ad(!plan->must_get_clust);
rw_lock_t* ahi_latch = btr_get_search_latch(index); row_sel_open_pcur(plan, mtr);
rw_lock_s_lock(ahi_latch);
row_sel_open_pcur(plan, ahi_latch, mtr);
const rec_t* rec = btr_pcur_get_rec(&(plan->pcur)); const rec_t* rec = btr_pcur_get_rec(&(plan->pcur));
if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) { if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) {
retry: retry:
rw_lock_s_unlock(ahi_latch);
return(SEL_RETRY); return(SEL_RETRY);
} }
@ -1493,7 +1485,6 @@ retry:
if (btr_pcur_get_up_match(&(plan->pcur)) < plan->n_exact_match) { if (btr_pcur_get_up_match(&(plan->pcur)) < plan->n_exact_match) {
exhausted: exhausted:
rw_lock_s_unlock(ahi_latch);
return(SEL_EXHAUSTED); return(SEL_EXHAUSTED);
} }
@ -1539,7 +1530,6 @@ exhausted:
ut_ad(plan->pcur.latch_mode == BTR_SEARCH_LEAF); ut_ad(plan->pcur.latch_mode == BTR_SEARCH_LEAF);
plan->n_rows_fetched++; plan->n_rows_fetched++;
rw_lock_s_unlock(ahi_latch);
if (UNIV_LIKELY_NULL(heap)) { if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap); mem_heap_free(heap);
@ -1661,11 +1651,7 @@ table_loop:
if (!plan->pcur_is_open) { if (!plan->pcur_is_open) {
/* Evaluate the expressions to build the search tuple and /* Evaluate the expressions to build the search tuple and
open the cursor */ open the cursor */
row_sel_open_pcur(plan, row_sel_open_pcur(plan, &mtr);
#ifdef BTR_CUR_HASH_ADAPT
NULL,
#endif /* BTR_CUR_HASH_ADAPT */
&mtr);
cursor_just_opened = TRUE; cursor_just_opened = TRUE;

View File

@ -576,9 +576,13 @@ warn::~warn()
sql_print_warning("InnoDB: %s", m_oss.str().c_str()); sql_print_warning("InnoDB: %s", m_oss.str().c_str());
} }
/** true if error::~error() was invoked, false otherwise */
bool error::logged;
error::~error() error::~error()
{ {
sql_print_error("InnoDB: %s", m_oss.str().c_str()); sql_print_error("InnoDB: %s", m_oss.str().c_str());
logged = true;
} }
#ifdef _MSC_VER #ifdef _MSC_VER

View File

@ -1288,6 +1288,7 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
uint byte= 6 * (last_insert_page / 16); uint byte= 6 * (last_insert_page / 16);
first_pattern= last_insert_page % 16; first_pattern= last_insert_page % 16;
data= bitmap->map+byte; data= bitmap->map+byte;
first_found= 0; /* Don't update full_head_size */
DBUG_ASSERT(data <= end); DBUG_ASSERT(data <= end);
} }
else else