mirror of
https://github.com/MariaDB/server.git
synced 2026-05-16 20:07:13 +02:00
Merge 10.2 into bb-10.2-ext
This commit is contained in:
commit
0c1f220611
24 changed files with 637 additions and 356 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
||||||
Copyright (c) 1995, 2017, MariaDB Corporation.
|
Copyright (c) 1995, 2018, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -205,6 +205,12 @@ enum ha_extra_function {
|
||||||
HA_EXTRA_PREPARE_FOR_FORCED_CLOSE,
|
HA_EXTRA_PREPARE_FOR_FORCED_CLOSE,
|
||||||
/* Inform handler that we will do an alter table */
|
/* Inform handler that we will do an alter table */
|
||||||
HA_EXTRA_PREPARE_FOR_ALTER_TABLE,
|
HA_EXTRA_PREPARE_FOR_ALTER_TABLE,
|
||||||
|
/** Start writing rows during ALTER TABLE...ALGORITHM=COPY. */
|
||||||
|
HA_EXTRA_BEGIN_ALTER_COPY,
|
||||||
|
/** Finish writing rows during ALTER TABLE...ALGORITHM=COPY. */
|
||||||
|
HA_EXTRA_END_ALTER_COPY,
|
||||||
|
/** Fake the start of a statement after wsrep_load_data_splitting hack */
|
||||||
|
HA_EXTRA_FAKE_START_STMT
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Compatible option, to be deleted in 6.0 */
|
/* Compatible option, to be deleted in 6.0 */
|
||||||
|
|
|
||||||
213
mysql-test/suite/innodb/r/alter_copy.result
Normal file
213
mysql-test/suite/innodb/r/alter_copy.result
Normal file
|
|
@ -0,0 +1,213 @@
|
||||||
|
#
|
||||||
|
# MDEV-11415 AVOID INTERMEDIATE COMMIT WHILE DOING
|
||||||
|
# ALTER TABLE...ALGORITHM=COPY
|
||||||
|
#
|
||||||
|
CREATE TABLE t(a SERIAL, b INT, c INT, d INT) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t1(a INT, b TEXT, c TEXT,
|
||||||
|
FULLTEXT(b), FULLTEXT(c(3)), FULLTEXT(b,c)) ENGINE=InnoDB;
|
||||||
|
BEGIN;
|
||||||
|
COMMIT;
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
COUNT(*)
|
||||||
|
999
|
||||||
|
UPDATE t SET b=a%7, c=a%11, d=a%13;
|
||||||
|
INSERT INTO t1 VALUES(1, 'This is a first b column', 'This is a first c column');
|
||||||
|
INSERT INTO t1 VALUES(2, 'This is a second b column', 'This is a second c column');
|
||||||
|
INSERT INTO t1(a) VALUES(3);
|
||||||
|
INSERT INTO t1 VALUES(4, 'This is a third b column', 'This is a third c column');
|
||||||
|
DELETE FROM t1 WHERE a = 2;
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||||
|
a b c
|
||||||
|
1 This is a first b column This is a first c column
|
||||||
|
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||||
|
a b c
|
||||||
|
1 This is a first b column This is a first c column
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||||
|
a b c
|
||||||
|
1 This is a first b column This is a first c column
|
||||||
|
4 This is a third b column This is a third c column
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` int(11) DEFAULT NULL,
|
||||||
|
`b` text DEFAULT NULL,
|
||||||
|
`c` text DEFAULT NULL,
|
||||||
|
FULLTEXT KEY `b` (`b`),
|
||||||
|
FULLTEXT KEY `c` (`c`),
|
||||||
|
FULLTEXT KEY `b_2` (`b`,`c`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
ALTER TABLE t1 FORCE, ALGORITHM=COPY;
|
||||||
|
SET DEBUG_DBUG='+d,crash_commit_before';
|
||||||
|
ALTER TABLE t ADD INDEX(b,c,d,a),ADD INDEX(b,c,a,d),ADD INDEX(b,a,c,d),ADD INDEX(b,a,d,c),
|
||||||
|
ADD INDEX(b,d,a,c),ADD INDEX(b,d,c,a),ADD INDEX(a,b,c,d),ADD INDEX(a,b,d,c),
|
||||||
|
ADD INDEX(a,c,b,d),ADD INDEX(a,c,d,b),ADD INDEX(a,d,b,c),ADD INDEX(a,d,c,b),
|
||||||
|
ADD INDEX(c,a,b,d),ADD INDEX(c,a,d,b),ADD INDEX(c,b,a,d),ADD INDEX(c,b,d,a),
|
||||||
|
ADD INDEX(c,d,a,b),ADD INDEX(c,d,b,a),ADD INDEX(d,a,b,c),ADD INDEX(d,a,c,b),
|
||||||
|
ADD INDEX(d,b,a,c),ADD INDEX(d,b,c,a),ADD INDEX(d,c,a,b),ADD INDEX(d,c,b,a),
|
||||||
|
ADD INDEX(a,b,c), ADD INDEX(a,c,b), ADD INDEX(a,c,d), ADD INDEX(a,d,c),
|
||||||
|
ADD INDEX(a,b,d), ADD INDEX(a,d,b), ADD INDEX(b,c,d), ADD INDEX(b,d,c),
|
||||||
|
ALGORITHM=COPY;
|
||||||
|
ERROR HY000: Lost connection to MySQL server during query
|
||||||
|
#sql-temporary.frm
|
||||||
|
#sql-temporary.ibd
|
||||||
|
FTS_INDEX_1.ibd
|
||||||
|
FTS_INDEX_2.ibd
|
||||||
|
FTS_INDEX_3.ibd
|
||||||
|
FTS_INDEX_4.ibd
|
||||||
|
FTS_INDEX_5.ibd
|
||||||
|
FTS_INDEX_6.ibd
|
||||||
|
FTS_INDEX_1.ibd
|
||||||
|
FTS_INDEX_2.ibd
|
||||||
|
FTS_INDEX_3.ibd
|
||||||
|
FTS_INDEX_4.ibd
|
||||||
|
FTS_INDEX_5.ibd
|
||||||
|
FTS_INDEX_6.ibd
|
||||||
|
FTS_INDEX_1.ibd
|
||||||
|
FTS_INDEX_2.ibd
|
||||||
|
FTS_INDEX_3.ibd
|
||||||
|
FTS_INDEX_4.ibd
|
||||||
|
FTS_INDEX_5.ibd
|
||||||
|
FTS_INDEX_6.ibd
|
||||||
|
FTSBEING_DELETED.ibd
|
||||||
|
FTSBEING_DELETED_CACHE.ibd
|
||||||
|
FTSCONFIG.ibd
|
||||||
|
FTSDELETED.ibd
|
||||||
|
FTSDELETED_CACHE.ibd
|
||||||
|
t.frm
|
||||||
|
t.ibd
|
||||||
|
t1.frm
|
||||||
|
t1.ibd
|
||||||
|
SHOW CREATE TABLE t;
|
||||||
|
Table Create Table
|
||||||
|
t CREATE TABLE `t` (
|
||||||
|
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`b` int(11) DEFAULT NULL,
|
||||||
|
`c` int(11) DEFAULT NULL,
|
||||||
|
`d` int(11) DEFAULT NULL,
|
||||||
|
UNIQUE KEY `a` (`a`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=latin1
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
COUNT(*)
|
||||||
|
999
|
||||||
|
CHECK TABLE t;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t check status OK
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||||
|
a b c
|
||||||
|
1 This is a first b column This is a first c column
|
||||||
|
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||||
|
a b c
|
||||||
|
1 This is a first b column This is a first c column
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||||
|
a b c
|
||||||
|
1 This is a first b column This is a first c column
|
||||||
|
4 This is a third b column This is a third c column
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` int(11) DEFAULT NULL,
|
||||||
|
`b` text DEFAULT NULL,
|
||||||
|
`c` text DEFAULT NULL,
|
||||||
|
FULLTEXT KEY `b` (`b`),
|
||||||
|
FULLTEXT KEY `c` (`c`),
|
||||||
|
FULLTEXT KEY `b_2` (`b`,`c`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
CHECK TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
|
#sql-temporary.frm
|
||||||
|
#sql-temporary.ibd
|
||||||
|
FTS_INDEX_1.ibd
|
||||||
|
FTS_INDEX_2.ibd
|
||||||
|
FTS_INDEX_3.ibd
|
||||||
|
FTS_INDEX_4.ibd
|
||||||
|
FTS_INDEX_5.ibd
|
||||||
|
FTS_INDEX_6.ibd
|
||||||
|
FTS_INDEX_1.ibd
|
||||||
|
FTS_INDEX_2.ibd
|
||||||
|
FTS_INDEX_3.ibd
|
||||||
|
FTS_INDEX_4.ibd
|
||||||
|
FTS_INDEX_5.ibd
|
||||||
|
FTS_INDEX_6.ibd
|
||||||
|
FTS_INDEX_1.ibd
|
||||||
|
FTS_INDEX_2.ibd
|
||||||
|
FTS_INDEX_3.ibd
|
||||||
|
FTS_INDEX_4.ibd
|
||||||
|
FTS_INDEX_5.ibd
|
||||||
|
FTS_INDEX_6.ibd
|
||||||
|
FTSBEING_DELETED.ibd
|
||||||
|
FTSBEING_DELETED_CACHE.ibd
|
||||||
|
FTSCONFIG.ibd
|
||||||
|
FTSDELETED.ibd
|
||||||
|
FTSDELETED_CACHE.ibd
|
||||||
|
t.frm
|
||||||
|
t.ibd
|
||||||
|
t1.frm
|
||||||
|
t1.ibd
|
||||||
|
SHOW CREATE TABLE t;
|
||||||
|
Table Create Table
|
||||||
|
t CREATE TABLE `t` (
|
||||||
|
`a` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`b` int(11) DEFAULT NULL,
|
||||||
|
`c` int(11) DEFAULT NULL,
|
||||||
|
`d` int(11) DEFAULT NULL,
|
||||||
|
UNIQUE KEY `a` (`a`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=latin1
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
COUNT(*)
|
||||||
|
999
|
||||||
|
CHECK TABLE t;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t check status OK
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||||
|
a b c
|
||||||
|
1 This is a first b column This is a first c column
|
||||||
|
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||||
|
a b c
|
||||||
|
1 This is a first b column This is a first c column
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||||
|
a b c
|
||||||
|
1 This is a first b column This is a first c column
|
||||||
|
4 This is a third b column This is a third c column
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`a` int(11) DEFAULT NULL,
|
||||||
|
`b` text DEFAULT NULL,
|
||||||
|
`c` text DEFAULT NULL,
|
||||||
|
FULLTEXT KEY `b` (`b`),
|
||||||
|
FULLTEXT KEY `c` (`c`),
|
||||||
|
FULLTEXT KEY `b_2` (`b`,`c`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
CHECK TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
|
#sql-temporary.frm
|
||||||
|
FTS_INDEX_1.ibd
|
||||||
|
FTS_INDEX_2.ibd
|
||||||
|
FTS_INDEX_3.ibd
|
||||||
|
FTS_INDEX_4.ibd
|
||||||
|
FTS_INDEX_5.ibd
|
||||||
|
FTS_INDEX_6.ibd
|
||||||
|
FTS_INDEX_1.ibd
|
||||||
|
FTS_INDEX_2.ibd
|
||||||
|
FTS_INDEX_3.ibd
|
||||||
|
FTS_INDEX_4.ibd
|
||||||
|
FTS_INDEX_5.ibd
|
||||||
|
FTS_INDEX_6.ibd
|
||||||
|
FTS_INDEX_1.ibd
|
||||||
|
FTS_INDEX_2.ibd
|
||||||
|
FTS_INDEX_3.ibd
|
||||||
|
FTS_INDEX_4.ibd
|
||||||
|
FTS_INDEX_5.ibd
|
||||||
|
FTS_INDEX_6.ibd
|
||||||
|
FTSBEING_DELETED.ibd
|
||||||
|
FTSBEING_DELETED_CACHE.ibd
|
||||||
|
FTSCONFIG.ibd
|
||||||
|
FTSDELETED.ibd
|
||||||
|
FTSDELETED_CACHE.ibd
|
||||||
|
t.frm
|
||||||
|
t.ibd
|
||||||
|
t1.frm
|
||||||
|
t1.ibd
|
||||||
|
DROP TABLE t1,t;
|
||||||
91
mysql-test/suite/innodb/t/alter_copy.test
Normal file
91
mysql-test/suite/innodb/t/alter_copy.test
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/have_debug.inc
|
||||||
|
--source include/have_debug_sync.inc
|
||||||
|
--source include/not_embedded.inc
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-11415 AVOID INTERMEDIATE COMMIT WHILE DOING
|
||||||
|
--echo # ALTER TABLE...ALGORITHM=COPY
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t(a SERIAL, b INT, c INT, d INT) ENGINE=InnoDB;
|
||||||
|
CREATE TABLE t1(a INT, b TEXT, c TEXT,
|
||||||
|
FULLTEXT(b), FULLTEXT(c(3)), FULLTEXT(b,c)) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
let $c = 999;
|
||||||
|
BEGIN;
|
||||||
|
--disable_query_log
|
||||||
|
while ($c) {
|
||||||
|
INSERT INTO t() VALUES();
|
||||||
|
dec $c;
|
||||||
|
}
|
||||||
|
--enable_query_log
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
# try to make the to-be-created secondary index keys randomly distributed
|
||||||
|
UPDATE t SET b=a%7, c=a%11, d=a%13;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES(1, 'This is a first b column', 'This is a first c column');
|
||||||
|
INSERT INTO t1 VALUES(2, 'This is a second b column', 'This is a second c column');
|
||||||
|
INSERT INTO t1(a) VALUES(3);
|
||||||
|
INSERT INTO t1 VALUES(4, 'This is a third b column', 'This is a third c column');
|
||||||
|
DELETE FROM t1 WHERE a = 2;
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||||
|
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
ALTER TABLE t1 FORCE, ALGORITHM=COPY;
|
||||||
|
|
||||||
|
# crash right after the last write_row(), before the first commit of ALTER TABLE
|
||||||
|
--source include/expect_crash.inc
|
||||||
|
|
||||||
|
SET DEBUG_DBUG='+d,crash_commit_before';
|
||||||
|
--error 2013
|
||||||
|
# create 32 secondary indexes
|
||||||
|
ALTER TABLE t ADD INDEX(b,c,d,a),ADD INDEX(b,c,a,d),ADD INDEX(b,a,c,d),ADD INDEX(b,a,d,c),
|
||||||
|
ADD INDEX(b,d,a,c),ADD INDEX(b,d,c,a),ADD INDEX(a,b,c,d),ADD INDEX(a,b,d,c),
|
||||||
|
ADD INDEX(a,c,b,d),ADD INDEX(a,c,d,b),ADD INDEX(a,d,b,c),ADD INDEX(a,d,c,b),
|
||||||
|
ADD INDEX(c,a,b,d),ADD INDEX(c,a,d,b),ADD INDEX(c,b,a,d),ADD INDEX(c,b,d,a),
|
||||||
|
ADD INDEX(c,d,a,b),ADD INDEX(c,d,b,a),ADD INDEX(d,a,b,c),ADD INDEX(d,a,c,b),
|
||||||
|
ADD INDEX(d,b,a,c),ADD INDEX(d,b,c,a),ADD INDEX(d,c,a,b),ADD INDEX(d,c,b,a),
|
||||||
|
ADD INDEX(a,b,c), ADD INDEX(a,c,b), ADD INDEX(a,c,d), ADD INDEX(a,d,c),
|
||||||
|
ADD INDEX(a,b,d), ADD INDEX(a,d,b), ADD INDEX(b,c,d), ADD INDEX(b,d,c),
|
||||||
|
ALGORITHM=COPY;
|
||||||
|
|
||||||
|
--let $restart_parameters= --innodb-force-recovery=3
|
||||||
|
--source include/start_mysqld.inc
|
||||||
|
let $datadir=`select @@datadir`;
|
||||||
|
--replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ /FTS_[0-9a-f]*_[0-9a-f]*/FTS/
|
||||||
|
--list_files $datadir/test
|
||||||
|
SHOW CREATE TABLE t;
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
CHECK TABLE t;
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||||
|
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
CHECK TABLE t1;
|
||||||
|
|
||||||
|
--let $restart_parameters= --innodb-read-only
|
||||||
|
--source include/restart_mysqld.inc
|
||||||
|
--replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ /FTS_[0-9a-f]*_[0-9a-f]*/FTS/
|
||||||
|
|
||||||
|
--list_files $datadir/test
|
||||||
|
SHOW CREATE TABLE t;
|
||||||
|
SELECT COUNT(*) FROM t;
|
||||||
|
CHECK TABLE t;
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b) AGAINST ('first');
|
||||||
|
SELECT * FROM t1 WHERE MATCH(c) AGAINST ('first');
|
||||||
|
SELECT * FROM t1 WHERE MATCH(b,c) AGAINST ('column');
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
CHECK TABLE t1;
|
||||||
|
|
||||||
|
--let $restart_parameters=
|
||||||
|
--source include/restart_mysqld.inc
|
||||||
|
--replace_regex /#sql-[0-9a-f_]*/#sql-temporary/ /FTS_[0-9a-f]*_[0-9a-f]*/FTS/
|
||||||
|
--list_files $datadir/test
|
||||||
|
DROP TABLE t1,t;
|
||||||
|
|
||||||
|
# Work around missing crash recovery at the SQL layer.
|
||||||
|
--remove_files_wildcard $datadir/test #sql-*.frm
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2005, 2017, Oracle and/or its affiliates.
|
Copyright (c) 2005, 2017, Oracle and/or its affiliates.
|
||||||
Copyright (c) 2009, 2017, MariaDB
|
Copyright (c) 2009, 2018, MariaDB
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -7260,6 +7260,10 @@ int ha_partition::extra(enum ha_extra_function operation)
|
||||||
*/
|
*/
|
||||||
case HA_EXTRA_MARK_AS_LOG_TABLE:
|
case HA_EXTRA_MARK_AS_LOG_TABLE:
|
||||||
DBUG_RETURN(ER_UNSUPORTED_LOG_ENGINE);
|
DBUG_RETURN(ER_UNSUPORTED_LOG_ENGINE);
|
||||||
|
case HA_EXTRA_BEGIN_ALTER_COPY:
|
||||||
|
case HA_EXTRA_END_ALTER_COPY:
|
||||||
|
case HA_EXTRA_FAKE_START_STMT:
|
||||||
|
DBUG_RETURN(loop_extra(operation));
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
/* Temporary crash to discover what is wrong */
|
/* Temporary crash to discover what is wrong */
|
||||||
|
|
|
||||||
|
|
@ -1103,6 +1103,7 @@ void make_default_log_name(char **out, const char* log_ext, bool once);
|
||||||
void binlog_reset_cache(THD *thd);
|
void binlog_reset_cache(THD *thd);
|
||||||
|
|
||||||
extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
|
extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
|
||||||
|
extern handlerton *binlog_hton;
|
||||||
extern LOGGER logger;
|
extern LOGGER logger;
|
||||||
|
|
||||||
extern const char *log_bin_index;
|
extern const char *log_bin_index;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
|
Copyright (c) 2000, 2016, Oracle and/or its affiliates.
|
||||||
Copyright (c) 2010, 2017, MariaDB Corporation
|
Copyright (c) 2010, 2018, MariaDB Corporation.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -97,6 +97,45 @@ public:
|
||||||
#define GET (stack_pos != stack ? *--stack_pos : my_b_get(&cache))
|
#define GET (stack_pos != stack ? *--stack_pos : my_b_get(&cache))
|
||||||
#define PUSH(A) *(stack_pos++)=(A)
|
#define PUSH(A) *(stack_pos++)=(A)
|
||||||
|
|
||||||
|
#ifdef WITH_WSREP
|
||||||
|
/** If requested by wsrep_load_data_splitting, commit and restart
|
||||||
|
the transaction after every 10,000 inserted rows. */
|
||||||
|
|
||||||
|
static bool wsrep_load_data_split(THD *thd, const TABLE *table,
|
||||||
|
const COPY_INFO &info)
|
||||||
|
{
|
||||||
|
extern struct handlerton* innodb_hton_ptr;
|
||||||
|
|
||||||
|
DBUG_ENTER("wsrep_load_data_split");
|
||||||
|
|
||||||
|
if (wsrep_load_data_splitting && wsrep_on(thd)
|
||||||
|
&& info.records && !(info.records % 10000)
|
||||||
|
&& thd->transaction.stmt.ha_list
|
||||||
|
&& thd->transaction.stmt.ha_list->ht() == binlog_hton
|
||||||
|
&& thd->transaction.stmt.ha_list->next()
|
||||||
|
&& thd->transaction.stmt.ha_list->next()->ht() == innodb_hton_ptr
|
||||||
|
&& !thd->transaction.stmt.ha_list->next()->next())
|
||||||
|
{
|
||||||
|
WSREP_DEBUG("intermediate transaction commit in LOAD DATA");
|
||||||
|
if (wsrep_run_wsrep_commit(thd, true) != WSREP_TRX_OK) DBUG_RETURN(true);
|
||||||
|
if (binlog_hton->commit(binlog_hton, thd, true)) DBUG_RETURN(true);
|
||||||
|
wsrep_post_commit(thd, true);
|
||||||
|
innodb_hton_ptr->commit(innodb_hton_ptr, thd, true);
|
||||||
|
table->file->extra(HA_EXTRA_FAKE_START_STMT);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
}
|
||||||
|
# define WSREP_LOAD_DATA_SPLIT(thd,table,info) \
|
||||||
|
if (wsrep_load_data_split(thd,table,info)) \
|
||||||
|
{ \
|
||||||
|
table->auto_increment_field_not_null= FALSE; \
|
||||||
|
DBUG_RETURN(1); \
|
||||||
|
}
|
||||||
|
#else /* WITH_WSREP */
|
||||||
|
#define WSREP_LOAD_DATA_SPLIT(thd,table,info) /* empty */
|
||||||
|
#endif /* WITH_WSREP */
|
||||||
|
|
||||||
class READ_INFO {
|
class READ_INFO {
|
||||||
File file;
|
File file;
|
||||||
String data; /* Read buffer */
|
String data; /* Read buffer */
|
||||||
|
|
@ -989,6 +1028,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WSREP_LOAD_DATA_SPLIT(thd, table, info);
|
||||||
err= write_record(thd, table, &info);
|
err= write_record(thd, table, &info);
|
||||||
table->auto_increment_field_not_null= FALSE;
|
table->auto_increment_field_not_null= FALSE;
|
||||||
if (err)
|
if (err)
|
||||||
|
|
@ -1194,6 +1234,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WSREP_LOAD_DATA_SPLIT(thd, table, info);
|
||||||
err= write_record(thd, table, &info);
|
err= write_record(thd, table, &info);
|
||||||
table->auto_increment_field_not_null= FALSE;
|
table->auto_increment_field_not_null= FALSE;
|
||||||
if (err)
|
if (err)
|
||||||
|
|
@ -1348,6 +1389,7 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WSREP_LOAD_DATA_SPLIT(thd, table, info);
|
||||||
err= write_record(thd, table, &info);
|
err= write_record(thd, table, &info);
|
||||||
table->auto_increment_field_not_null= false;
|
table->auto_increment_field_not_null= false;
|
||||||
if (err)
|
if (err)
|
||||||
|
|
|
||||||
|
|
@ -9794,6 +9794,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||||
|
|
||||||
thd->progress.max_counter= from->file->records();
|
thd->progress.max_counter= from->file->records();
|
||||||
time_to_report_progress= MY_HOW_OFTEN_TO_WRITE/10;
|
time_to_report_progress= MY_HOW_OFTEN_TO_WRITE/10;
|
||||||
|
if (!ignore) /* for now, InnoDB needs the undo log for ALTER IGNORE */
|
||||||
|
to->file->extra(HA_EXTRA_BEGIN_ALTER_COPY);
|
||||||
|
|
||||||
while (!(error=info.read_record(&info)))
|
while (!(error=info.read_record(&info)))
|
||||||
{
|
{
|
||||||
|
|
@ -9918,6 +9920,8 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
|
||||||
to->file->print_error(my_errno,MYF(0));
|
to->file->print_error(my_errno,MYF(0));
|
||||||
error= 1;
|
error= 1;
|
||||||
}
|
}
|
||||||
|
if (!ignore)
|
||||||
|
to->file->extra(HA_EXTRA_END_ALTER_COPY);
|
||||||
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||||
|
|
||||||
if (mysql_trans_commit_alter_copy_data(thd))
|
if (mysql_trans_commit_alter_copy_data(thd))
|
||||||
|
|
|
||||||
|
|
@ -2303,7 +2303,6 @@ fts_savepoint_create(
|
||||||
/******************************************************************//**
|
/******************************************************************//**
|
||||||
Create an FTS trx.
|
Create an FTS trx.
|
||||||
@return FTS trx */
|
@return FTS trx */
|
||||||
static
|
|
||||||
fts_trx_t*
|
fts_trx_t*
|
||||||
fts_trx_create(
|
fts_trx_create(
|
||||||
/*===========*/
|
/*===========*/
|
||||||
|
|
@ -3332,6 +3331,144 @@ fts_fetch_doc_from_rec(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Fetch the data from tuple and tokenize the document.
|
||||||
|
@param[in] get_doc FTS index's get_doc struct
|
||||||
|
@param[in] tuple tuple should be arranged in table schema order
|
||||||
|
@param[out] doc fts doc to hold parsed documents. */
|
||||||
|
static
|
||||||
|
void
|
||||||
|
fts_fetch_doc_from_tuple(
|
||||||
|
fts_get_doc_t* get_doc,
|
||||||
|
const dtuple_t* tuple,
|
||||||
|
fts_doc_t* doc)
|
||||||
|
{
|
||||||
|
dict_index_t* index;
|
||||||
|
st_mysql_ftparser* parser;
|
||||||
|
ulint doc_len = 0;
|
||||||
|
ulint processed_doc = 0;
|
||||||
|
ulint num_field;
|
||||||
|
|
||||||
|
if (get_doc == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = get_doc->index_cache->index;
|
||||||
|
parser = get_doc->index_cache->index->parser;
|
||||||
|
num_field = dict_index_get_n_fields(index);
|
||||||
|
|
||||||
|
for (ulint i = 0; i < num_field; i++) {
|
||||||
|
const dict_field_t* ifield;
|
||||||
|
const dict_col_t* col;
|
||||||
|
ulint pos;
|
||||||
|
dfield_t* field;
|
||||||
|
|
||||||
|
ifield = dict_index_get_nth_field(index, i);
|
||||||
|
col = dict_field_get_col(ifield);
|
||||||
|
pos = dict_col_get_no(col);
|
||||||
|
field = dtuple_get_nth_field(tuple, pos);
|
||||||
|
|
||||||
|
if (!get_doc->index_cache->charset) {
|
||||||
|
get_doc->index_cache->charset = fts_get_charset(
|
||||||
|
ifield->col->prtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
ut_ad(!dfield_is_ext(field));
|
||||||
|
|
||||||
|
doc->text.f_str = (byte*) dfield_get_data(field);
|
||||||
|
doc->text.f_len = dfield_get_len(field);
|
||||||
|
doc->found = TRUE;
|
||||||
|
doc->charset = get_doc->index_cache->charset;
|
||||||
|
|
||||||
|
/* field data is NULL. */
|
||||||
|
if (doc->text.f_len == UNIV_SQL_NULL || doc->text.f_len == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed_doc == 0) {
|
||||||
|
fts_tokenize_document(doc, NULL, parser);
|
||||||
|
} else {
|
||||||
|
fts_tokenize_document_next(doc, doc_len, NULL, parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
processed_doc++;
|
||||||
|
doc_len += doc->text.f_len + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fetch the document from tuple, tokenize the text data and
|
||||||
|
insert the text data into fts auxiliary table and
|
||||||
|
its cache. Moreover this tuple fields doesn't contain any information
|
||||||
|
about externally stored field. This tuple contains data directly
|
||||||
|
converted from mysql.
|
||||||
|
@param[in] ftt FTS transaction table
|
||||||
|
@param[in] doc_id doc id
|
||||||
|
@param[in] tuple tuple from where data can be retrieved
|
||||||
|
and tuple should be arranged in table
|
||||||
|
schema order. */
|
||||||
|
void
|
||||||
|
fts_add_doc_from_tuple(
|
||||||
|
fts_trx_table_t*ftt,
|
||||||
|
doc_id_t doc_id,
|
||||||
|
const dtuple_t* tuple)
|
||||||
|
{
|
||||||
|
mtr_t mtr;
|
||||||
|
fts_cache_t* cache = ftt->table->fts->cache;
|
||||||
|
|
||||||
|
ut_ad(cache->get_docs);
|
||||||
|
|
||||||
|
if (!(ftt->table->fts->fts_status & ADDED_TABLE_SYNCED)) {
|
||||||
|
fts_init_index(ftt->table, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mtr_start(&mtr);
|
||||||
|
|
||||||
|
ulint num_idx = ib_vector_size(cache->get_docs);
|
||||||
|
|
||||||
|
for (ulint i = 0; i < num_idx; ++i) {
|
||||||
|
fts_doc_t doc;
|
||||||
|
dict_table_t* table;
|
||||||
|
fts_get_doc_t* get_doc;
|
||||||
|
|
||||||
|
get_doc = static_cast<fts_get_doc_t*>(
|
||||||
|
ib_vector_get(cache->get_docs, i));
|
||||||
|
table = get_doc->index_cache->index->table;
|
||||||
|
|
||||||
|
fts_doc_init(&doc);
|
||||||
|
fts_fetch_doc_from_tuple(
|
||||||
|
get_doc, tuple, &doc);
|
||||||
|
|
||||||
|
if (doc.found) {
|
||||||
|
mtr_commit(&mtr);
|
||||||
|
rw_lock_x_lock(&table->fts->cache->lock);
|
||||||
|
|
||||||
|
if (table->fts->cache->stopword_info.status
|
||||||
|
& STOPWORD_NOT_INIT) {
|
||||||
|
fts_load_stopword(table, NULL, NULL,
|
||||||
|
NULL, TRUE, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
fts_cache_add_doc(
|
||||||
|
table->fts->cache,
|
||||||
|
get_doc->index_cache,
|
||||||
|
doc_id, doc.tokens);
|
||||||
|
|
||||||
|
rw_lock_x_unlock(&table->fts->cache->lock);
|
||||||
|
|
||||||
|
if (cache->total_size > fts_max_cache_size / 5
|
||||||
|
|| fts_need_sync) {
|
||||||
|
fts_sync(cache->sync, true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
mtr_start(&mtr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fts_doc_free(&doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
mtr_commit(&mtr);
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
This function fetches the document inserted during the committing
|
This function fetches the document inserted during the committing
|
||||||
transaction, and tokenize the inserted text data and insert into
|
transaction, and tokenize the inserted text data and insert into
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ static mysql_mutex_t pending_checkpoint_mutex;
|
||||||
|
|
||||||
#define EQ_CURRENT_THD(thd) ((thd) == current_thd)
|
#define EQ_CURRENT_THD(thd) ((thd) == current_thd)
|
||||||
|
|
||||||
static struct handlerton* innodb_hton_ptr;
|
struct handlerton* innodb_hton_ptr;
|
||||||
|
|
||||||
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
|
static const long AUTOINC_OLD_STYLE_LOCKING = 0;
|
||||||
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
|
static const long AUTOINC_NEW_STYLE_LOCKING = 1;
|
||||||
|
|
@ -3069,7 +3069,6 @@ ha_innobase::ha_innobase(
|
||||||
| (srv_force_primary_key ? HA_REQUIRE_PRIMARY_KEY : 0)
|
| (srv_force_primary_key ? HA_REQUIRE_PRIMARY_KEY : 0)
|
||||||
),
|
),
|
||||||
m_start_of_scan(),
|
m_start_of_scan(),
|
||||||
m_num_write_row(),
|
|
||||||
m_mysql_has_locked()
|
m_mysql_has_locked()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
@ -8363,7 +8362,6 @@ ha_innobase::write_row(
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
ibool auto_inc_inserted= FALSE; /* if NULL was inserted */
|
ibool auto_inc_inserted= FALSE; /* if NULL was inserted */
|
||||||
#endif
|
#endif
|
||||||
ulint sql_command;
|
|
||||||
int error_result = 0;
|
int error_result = 0;
|
||||||
bool auto_inc_used = false;
|
bool auto_inc_used = false;
|
||||||
|
|
||||||
|
|
@ -8380,7 +8378,7 @@ ha_innobase::write_row(
|
||||||
DB_FORCED_ABORT, 0, m_user_thd));
|
DB_FORCED_ABORT, 0, m_user_thd));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step-1: Validation checks before we commence write_row operation. */
|
/* Validation checks before we commence write_row operation. */
|
||||||
if (high_level_read_only) {
|
if (high_level_read_only) {
|
||||||
ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
|
ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
|
||||||
DBUG_RETURN(HA_ERR_TABLE_READONLY);
|
DBUG_RETURN(HA_ERR_TABLE_READONLY);
|
||||||
|
|
@ -8401,131 +8399,7 @@ ha_innobase::write_row(
|
||||||
++trx->will_lock;
|
++trx->will_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step-2: Intermediate commit if original operation involves ALTER
|
/* Handling of Auto-Increment Columns. */
|
||||||
table with algorithm = copy. Intermediate commit ease pressure on
|
|
||||||
recovery if server crashes while ALTER is active. */
|
|
||||||
sql_command = thd_sql_command(m_user_thd);
|
|
||||||
|
|
||||||
if ((sql_command == SQLCOM_ALTER_TABLE
|
|
||||||
|| sql_command == SQLCOM_OPTIMIZE
|
|
||||||
|| sql_command == SQLCOM_CREATE_INDEX
|
|
||||||
#ifdef WITH_WSREP
|
|
||||||
|| (sql_command == SQLCOM_LOAD
|
|
||||||
&& wsrep_load_data_splitting && wsrep_on(m_user_thd)
|
|
||||||
&& !thd_test_options(
|
|
||||||
m_user_thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
|
|
||||||
#endif /* WITH_WSREP */
|
|
||||||
|| sql_command == SQLCOM_DROP_INDEX)
|
|
||||||
&& m_num_write_row >= 10000) {
|
|
||||||
#ifdef WITH_WSREP
|
|
||||||
if (sql_command == SQLCOM_LOAD && wsrep_on(m_user_thd)) {
|
|
||||||
WSREP_DEBUG("forced trx split for LOAD: %s",
|
|
||||||
wsrep_thd_query(m_user_thd));
|
|
||||||
}
|
|
||||||
#endif /* WITH_WSREP */
|
|
||||||
/* ALTER TABLE is COMMITted at every 10000 copied rows.
|
|
||||||
The IX table lock for the original table has to be re-issued.
|
|
||||||
As this method will be called on a temporary table where the
|
|
||||||
contents of the original table is being copied to, it is
|
|
||||||
a bit tricky to determine the source table. The cursor
|
|
||||||
position in the source table need not be adjusted after the
|
|
||||||
intermediate COMMIT, since writes by other transactions are
|
|
||||||
being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
|
|
||||||
|
|
||||||
dict_table_t* src_table;
|
|
||||||
enum lock_mode mode;
|
|
||||||
|
|
||||||
m_num_write_row = 0;
|
|
||||||
|
|
||||||
/* Commit the transaction. This will release the table
|
|
||||||
locks, so they have to be acquired again. */
|
|
||||||
|
|
||||||
/* Altering an InnoDB table */
|
|
||||||
/* Get the source table. */
|
|
||||||
src_table = lock_get_src_table(
|
|
||||||
m_prebuilt->trx, m_prebuilt->table, &mode);
|
|
||||||
if (!src_table) {
|
|
||||||
no_commit:
|
|
||||||
/* Unknown situation: do not commit */
|
|
||||||
;
|
|
||||||
} else if (src_table == m_prebuilt->table) {
|
|
||||||
#ifdef WITH_WSREP
|
|
||||||
if (wsrep_on(m_user_thd) &&
|
|
||||||
wsrep_load_data_splitting &&
|
|
||||||
sql_command == SQLCOM_LOAD &&
|
|
||||||
!thd_test_options(m_user_thd,
|
|
||||||
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
|
|
||||||
{
|
|
||||||
switch (wsrep_run_wsrep_commit(m_user_thd, 1)) {
|
|
||||||
case WSREP_TRX_OK:
|
|
||||||
break;
|
|
||||||
case WSREP_TRX_SIZE_EXCEEDED:
|
|
||||||
case WSREP_TRX_CERT_FAIL:
|
|
||||||
case WSREP_TRX_ERROR:
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (binlog_hton->commit(binlog_hton, m_user_thd, 1)) {
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
wsrep_post_commit(m_user_thd, TRUE);
|
|
||||||
}
|
|
||||||
#endif /* WITH_WSREP */
|
|
||||||
/* Source table is not in InnoDB format:
|
|
||||||
no need to re-acquire locks on it. */
|
|
||||||
|
|
||||||
/* Altering to InnoDB format */
|
|
||||||
innobase_commit(ht, m_user_thd, 1);
|
|
||||||
/* Note that this transaction is still active. */
|
|
||||||
trx_register_for_2pc(m_prebuilt->trx);
|
|
||||||
/* We will need an IX lock on the destination table. */
|
|
||||||
m_prebuilt->sql_stat_start = TRUE;
|
|
||||||
} else {
|
|
||||||
#ifdef WITH_WSREP
|
|
||||||
if (wsrep_on(m_user_thd) &&
|
|
||||||
wsrep_load_data_splitting &&
|
|
||||||
sql_command == SQLCOM_LOAD &&
|
|
||||||
!thd_test_options(m_user_thd,
|
|
||||||
OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
|
|
||||||
switch (wsrep_run_wsrep_commit(m_user_thd, 1)) {
|
|
||||||
case WSREP_TRX_OK:
|
|
||||||
break;
|
|
||||||
case WSREP_TRX_SIZE_EXCEEDED:
|
|
||||||
case WSREP_TRX_CERT_FAIL:
|
|
||||||
case WSREP_TRX_ERROR:
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (binlog_hton->commit(binlog_hton, m_user_thd, 1)) {
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
wsrep_post_commit(m_user_thd, TRUE);
|
|
||||||
}
|
|
||||||
#endif /* WITH_WSREP */
|
|
||||||
/* Ensure that there are no other table locks than
|
|
||||||
LOCK_IX and LOCK_AUTO_INC on the destination table. */
|
|
||||||
|
|
||||||
if (!lock_is_table_exclusive(m_prebuilt->table,
|
|
||||||
m_prebuilt->trx)) {
|
|
||||||
goto no_commit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Commit the transaction. This will release the table
|
|
||||||
locks, so they have to be acquired again. */
|
|
||||||
innobase_commit(ht, m_user_thd, 1);
|
|
||||||
/* Note that this transaction is still active. */
|
|
||||||
trx_register_for_2pc(m_prebuilt->trx);
|
|
||||||
/* Re-acquire the table lock on the source table. */
|
|
||||||
row_lock_table_for_mysql(m_prebuilt, src_table, mode);
|
|
||||||
/* We will need an IX lock on the destination table. */
|
|
||||||
m_prebuilt->sql_stat_start = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_num_write_row++;
|
|
||||||
|
|
||||||
/* Step-3: Handling of Auto-Increment Columns. */
|
|
||||||
if (table->next_number_field && record == table->record[0]) {
|
if (table->next_number_field && record == table->record[0]) {
|
||||||
|
|
||||||
/* Reset the error code before calling
|
/* Reset the error code before calling
|
||||||
|
|
@ -8558,7 +8432,7 @@ no_commit:
|
||||||
auto_inc_used = true;
|
auto_inc_used = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step-4: Prepare INSERT graph that will be executed for actual INSERT
|
/* Prepare INSERT graph that will be executed for actual INSERT
|
||||||
(This is a one time operation) */
|
(This is a one time operation) */
|
||||||
if (m_prebuilt->mysql_template == NULL
|
if (m_prebuilt->mysql_template == NULL
|
||||||
|| m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
|
|| m_prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
|
||||||
|
|
@ -8571,12 +8445,12 @@ no_commit:
|
||||||
|
|
||||||
innobase_srv_conc_enter_innodb(m_prebuilt);
|
innobase_srv_conc_enter_innodb(m_prebuilt);
|
||||||
|
|
||||||
/* Step-5: Execute insert graph that will result in actual insert. */
|
/* Execute insert graph that will result in actual insert. */
|
||||||
error = row_insert_for_mysql((byte*) record, m_prebuilt);
|
error = row_insert_for_mysql((byte*) record, m_prebuilt);
|
||||||
|
|
||||||
DEBUG_SYNC(m_user_thd, "ib_after_row_insert");
|
DEBUG_SYNC(m_user_thd, "ib_after_row_insert");
|
||||||
|
|
||||||
/* Step-6: Handling of errors related to auto-increment. */
|
/* Handling of errors related to auto-increment. */
|
||||||
if (auto_inc_used) {
|
if (auto_inc_used) {
|
||||||
ulonglong auto_inc;
|
ulonglong auto_inc;
|
||||||
ulonglong col_max_value;
|
ulonglong col_max_value;
|
||||||
|
|
@ -8604,13 +8478,11 @@ no_commit:
|
||||||
must update the autoinc counter if we are performing
|
must update the autoinc counter if we are performing
|
||||||
those statements. */
|
those statements. */
|
||||||
|
|
||||||
switch (sql_command) {
|
switch (thd_sql_command(m_user_thd)) {
|
||||||
case SQLCOM_LOAD:
|
case SQLCOM_LOAD:
|
||||||
if (trx->duplicates) {
|
if (!trx->duplicates) {
|
||||||
|
break;
|
||||||
goto set_max_autoinc;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case SQLCOM_REPLACE:
|
case SQLCOM_REPLACE:
|
||||||
case SQLCOM_INSERT_SELECT:
|
case SQLCOM_INSERT_SELECT:
|
||||||
|
|
@ -8699,7 +8571,7 @@ set_max_autoinc:
|
||||||
innobase_srv_conc_exit_innodb(m_prebuilt);
|
innobase_srv_conc_exit_innodb(m_prebuilt);
|
||||||
|
|
||||||
report_error:
|
report_error:
|
||||||
/* Step-7: Cleanup and exit. */
|
/* Cleanup and exit. */
|
||||||
if (error == DB_TABLESPACE_DELETED) {
|
if (error == DB_TABLESPACE_DELETED) {
|
||||||
ib_senderrf(
|
ib_senderrf(
|
||||||
trx->mysql_thd, IB_LOG_LEVEL_ERROR,
|
trx->mysql_thd, IB_LOG_LEVEL_ERROR,
|
||||||
|
|
@ -15967,6 +15839,16 @@ ha_innobase::extra(
|
||||||
case HA_EXTRA_WRITE_CANNOT_REPLACE:
|
case HA_EXTRA_WRITE_CANNOT_REPLACE:
|
||||||
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
|
thd_to_trx(ha_thd())->duplicates &= ~TRX_DUP_REPLACE;
|
||||||
break;
|
break;
|
||||||
|
case HA_EXTRA_BEGIN_ALTER_COPY:
|
||||||
|
m_prebuilt->table->skip_alter_undo = 1;
|
||||||
|
break;
|
||||||
|
case HA_EXTRA_END_ALTER_COPY:
|
||||||
|
m_prebuilt->table->skip_alter_undo = 0;
|
||||||
|
break;
|
||||||
|
case HA_EXTRA_FAKE_START_STMT:
|
||||||
|
trx_register_for_2pc(m_prebuilt->trx);
|
||||||
|
m_prebuilt->sql_stat_start = true;
|
||||||
|
break;
|
||||||
default:/* Do nothing */
|
default:/* Do nothing */
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
@ -16069,7 +15951,7 @@ ha_innobase::start_stmt(
|
||||||
init_table_handle_for_HANDLER();
|
init_table_handle_for_HANDLER();
|
||||||
m_prebuilt->select_lock_type = LOCK_X;
|
m_prebuilt->select_lock_type = LOCK_X;
|
||||||
m_prebuilt->stored_select_lock_type = LOCK_X;
|
m_prebuilt->stored_select_lock_type = LOCK_X;
|
||||||
error = row_lock_table_for_mysql(m_prebuilt, NULL, 1);
|
error = row_lock_table(m_prebuilt);
|
||||||
|
|
||||||
if (error != DB_SUCCESS) {
|
if (error != DB_SUCCESS) {
|
||||||
int st = convert_error_code_to_mysql(
|
int st = convert_error_code_to_mysql(
|
||||||
|
|
@ -16333,8 +16215,7 @@ ha_innobase::external_lock(
|
||||||
&& thd_test_options(thd, OPTION_NOT_AUTOCOMMIT)
|
&& thd_test_options(thd, OPTION_NOT_AUTOCOMMIT)
|
||||||
&& thd_in_lock_tables(thd)) {
|
&& thd_in_lock_tables(thd)) {
|
||||||
|
|
||||||
dberr_t error = row_lock_table_for_mysql(
|
dberr_t error = row_lock_table(m_prebuilt);
|
||||||
m_prebuilt, NULL, 0);
|
|
||||||
|
|
||||||
if (error != DB_SUCCESS) {
|
if (error != DB_SUCCESS) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -515,9 +515,6 @@ protected:
|
||||||
ROW_SEL_EXACT_PREFIX, or undefined */
|
ROW_SEL_EXACT_PREFIX, or undefined */
|
||||||
uint m_last_match_mode;
|
uint m_last_match_mode;
|
||||||
|
|
||||||
/** number of write_row() calls */
|
|
||||||
uint m_num_write_row;
|
|
||||||
|
|
||||||
/** If mysql has locked with external_lock() */
|
/** If mysql has locked with external_lock() */
|
||||||
bool m_mysql_has_locked;
|
bool m_mysql_has_locked;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1400,6 +1400,13 @@ struct dict_table_t {
|
||||||
Use DICT_TF2_FLAG_IS_SET() to parse this flag. */
|
Use DICT_TF2_FLAG_IS_SET() to parse this flag. */
|
||||||
unsigned flags2:DICT_TF2_BITS;
|
unsigned flags2:DICT_TF2_BITS;
|
||||||
|
|
||||||
|
/** TRUE if the table is an intermediate table during copy alter
|
||||||
|
operation or a partition/subpartition which is required for copying
|
||||||
|
data and skip the undo log for insertion of row in the table.
|
||||||
|
This variable will be set and unset during extra(), or during the
|
||||||
|
process of altering partitions */
|
||||||
|
unsigned skip_alter_undo:1;
|
||||||
|
|
||||||
/*!< whether this is in a single-table tablespace and the .ibd
|
/*!< whether this is in a single-table tablespace and the .ibd
|
||||||
file is missing or page decryption failed and page is corrupted */
|
file is missing or page decryption failed and page is corrupted */
|
||||||
unsigned file_unreadable:1;
|
unsigned file_unreadable:1;
|
||||||
|
|
|
||||||
|
|
@ -1015,5 +1015,27 @@ fts_check_corrupt(
|
||||||
dict_table_t* base_table,
|
dict_table_t* base_table,
|
||||||
trx_t* trx);
|
trx_t* trx);
|
||||||
|
|
||||||
|
/** Fetch the document from tuple, tokenize the text data and
|
||||||
|
insert the text data into fts auxiliary table and
|
||||||
|
its cache. Moreover this tuple fields doesn't contain any information
|
||||||
|
about externally stored field. This tuple contains data directly
|
||||||
|
converted from mysql.
|
||||||
|
@param[in] ftt FTS transaction table
|
||||||
|
@param[in] doc_id doc id
|
||||||
|
@param[in] tuple tuple from where data can be retrieved
|
||||||
|
and tuple should be arranged in table
|
||||||
|
schema order. */
|
||||||
|
void
|
||||||
|
fts_add_doc_from_tuple(
|
||||||
|
fts_trx_table_t*ftt,
|
||||||
|
doc_id_t doc_id,
|
||||||
|
const dtuple_t* tuple);
|
||||||
|
|
||||||
|
/** Create an FTS trx.
|
||||||
|
@param[in,out] trx InnoDB Transaction
|
||||||
|
@return FTS transaction. */
|
||||||
|
fts_trx_t*
|
||||||
|
fts_trx_create(
|
||||||
|
trx_t* trx);
|
||||||
|
|
||||||
#endif /*!< fts0fts.h */
|
#endif /*!< fts0fts.h */
|
||||||
|
|
|
||||||
|
|
@ -566,30 +566,6 @@ lock_rec_find_set_bit(
|
||||||
bit set */
|
bit set */
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
Gets the source table of an ALTER TABLE transaction. The table must be
|
|
||||||
covered by an IX or IS table lock.
|
|
||||||
@return the source table of transaction, if it is covered by an IX or
|
|
||||||
IS table lock; dest if there is no source table, and NULL if the
|
|
||||||
transaction is locking more than two tables or an inconsistency is
|
|
||||||
found */
|
|
||||||
dict_table_t*
|
|
||||||
lock_get_src_table(
|
|
||||||
/*===============*/
|
|
||||||
trx_t* trx, /*!< in: transaction */
|
|
||||||
dict_table_t* dest, /*!< in: destination of ALTER TABLE */
|
|
||||||
lock_mode* mode); /*!< out: lock mode of the source table */
|
|
||||||
/*********************************************************************//**
|
|
||||||
Determine if the given table is exclusively "owned" by the given
|
|
||||||
transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
|
|
||||||
on the table.
|
|
||||||
@return TRUE if table is only locked by trx, with LOCK_IX, and
|
|
||||||
possibly LOCK_AUTO_INC */
|
|
||||||
ibool
|
|
||||||
lock_is_table_exclusive(
|
|
||||||
/*====================*/
|
|
||||||
const dict_table_t* table, /*!< in: table */
|
|
||||||
const trx_t* trx); /*!< in: transaction */
|
|
||||||
/*********************************************************************//**
|
|
||||||
Checks if a lock request lock1 has to wait for request lock2.
|
Checks if a lock request lock1 has to wait for request lock2.
|
||||||
@return TRUE if lock1 has to wait for lock2 to be removed */
|
@return TRUE if lock1 has to wait for lock2 to be removed */
|
||||||
ibool
|
ibool
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
Copyright (c) 2017, MariaDB Corporation.
|
Copyright (c) 2017, 2018, 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
|
||||||
|
|
@ -219,21 +219,11 @@ row_lock_table_autoinc_for_mysql(
|
||||||
table handle */
|
table handle */
|
||||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||||
|
|
||||||
/*********************************************************************//**
|
/** Lock a table.
|
||||||
Sets a table lock on the table mentioned in prebuilt.
|
@param[in,out] prebuilt table handle
|
||||||
@return error code or DB_SUCCESS */
|
@return error code or DB_SUCCESS */
|
||||||
dberr_t
|
dberr_t
|
||||||
row_lock_table_for_mysql(
|
row_lock_table(row_prebuilt_t* prebuilt);
|
||||||
/*=====================*/
|
|
||||||
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct in the MySQL
|
|
||||||
table handle */
|
|
||||||
dict_table_t* table, /*!< in: table to lock, or NULL
|
|
||||||
if prebuilt->table should be
|
|
||||||
locked as
|
|
||||||
prebuilt->select_lock_type */
|
|
||||||
ulint mode) /*!< in: lock mode of table
|
|
||||||
(ignored if table==NULL) */
|
|
||||||
MY_ATTRIBUTE((nonnull(1)));
|
|
||||||
|
|
||||||
/** Does an insert for MySQL.
|
/** Does an insert for MySQL.
|
||||||
@param[in] mysql_rec row in the MySQL format
|
@param[in] mysql_rec row in the MySQL format
|
||||||
|
|
|
||||||
|
|
@ -619,145 +619,6 @@ lock_get_size(void)
|
||||||
return((ulint) sizeof(lock_t));
|
return((ulint) sizeof(lock_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
|
||||||
Gets the source table of an ALTER TABLE transaction. The table must be
|
|
||||||
covered by an IX or IS table lock.
|
|
||||||
@return the source table of transaction, if it is covered by an IX or
|
|
||||||
IS table lock; dest if there is no source table, and NULL if the
|
|
||||||
transaction is locking more than two tables or an inconsistency is
|
|
||||||
found */
|
|
||||||
dict_table_t*
|
|
||||||
lock_get_src_table(
|
|
||||||
/*===============*/
|
|
||||||
trx_t* trx, /*!< in: transaction */
|
|
||||||
dict_table_t* dest, /*!< in: destination of ALTER TABLE */
|
|
||||||
lock_mode* mode) /*!< out: lock mode of the source table */
|
|
||||||
{
|
|
||||||
dict_table_t* src;
|
|
||||||
lock_t* lock;
|
|
||||||
|
|
||||||
ut_ad(!lock_mutex_own());
|
|
||||||
|
|
||||||
src = NULL;
|
|
||||||
*mode = LOCK_NONE;
|
|
||||||
|
|
||||||
/* The trx mutex protects the trx_locks for our purposes.
|
|
||||||
Other transactions could want to convert one of our implicit
|
|
||||||
record locks to an explicit one. For that, they would need our
|
|
||||||
trx mutex. Waiting locks can be removed while only holding
|
|
||||||
lock_sys->mutex, but this is a running transaction and cannot
|
|
||||||
thus be holding any waiting locks. */
|
|
||||||
trx_mutex_enter(trx);
|
|
||||||
|
|
||||||
for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
|
|
||||||
lock != NULL;
|
|
||||||
lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
|
|
||||||
lock_table_t* tab_lock;
|
|
||||||
lock_mode lock_mode;
|
|
||||||
if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
|
|
||||||
/* We are only interested in table locks. */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tab_lock = &lock->un_member.tab_lock;
|
|
||||||
if (dest == tab_lock->table) {
|
|
||||||
/* We are not interested in the destination table. */
|
|
||||||
continue;
|
|
||||||
} else if (!src) {
|
|
||||||
/* This presumably is the source table. */
|
|
||||||
src = tab_lock->table;
|
|
||||||
if (UT_LIST_GET_LEN(src->locks) != 1
|
|
||||||
|| UT_LIST_GET_FIRST(src->locks) != lock) {
|
|
||||||
/* We only support the case when
|
|
||||||
there is only one lock on this table. */
|
|
||||||
src = NULL;
|
|
||||||
goto func_exit;
|
|
||||||
}
|
|
||||||
} else if (src != tab_lock->table) {
|
|
||||||
/* The transaction is locking more than
|
|
||||||
two tables (src and dest): abort */
|
|
||||||
src = NULL;
|
|
||||||
goto func_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that the source table is locked by
|
|
||||||
LOCK_IX or LOCK_IS. */
|
|
||||||
lock_mode = lock_get_mode(lock);
|
|
||||||
if (lock_mode == LOCK_IX || lock_mode == LOCK_IS) {
|
|
||||||
if (*mode != LOCK_NONE && *mode != lock_mode) {
|
|
||||||
/* There are multiple locks on src. */
|
|
||||||
src = NULL;
|
|
||||||
goto func_exit;
|
|
||||||
}
|
|
||||||
*mode = lock_mode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!src) {
|
|
||||||
/* No source table lock found: flag the situation to caller */
|
|
||||||
src = dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
func_exit:
|
|
||||||
trx_mutex_exit(trx);
|
|
||||||
return(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************//**
|
|
||||||
Determine if the given table is exclusively "owned" by the given
|
|
||||||
transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
|
|
||||||
on the table.
|
|
||||||
@return TRUE if table is only locked by trx, with LOCK_IX, and
|
|
||||||
possibly LOCK_AUTO_INC */
|
|
||||||
ibool
|
|
||||||
lock_is_table_exclusive(
|
|
||||||
/*====================*/
|
|
||||||
const dict_table_t* table, /*!< in: table */
|
|
||||||
const trx_t* trx) /*!< in: transaction */
|
|
||||||
{
|
|
||||||
const lock_t* lock;
|
|
||||||
ibool ok = FALSE;
|
|
||||||
|
|
||||||
ut_ad(table);
|
|
||||||
ut_ad(trx);
|
|
||||||
|
|
||||||
lock_mutex_enter();
|
|
||||||
|
|
||||||
for (lock = UT_LIST_GET_FIRST(table->locks);
|
|
||||||
lock != NULL;
|
|
||||||
lock = UT_LIST_GET_NEXT(locks, &lock->un_member.tab_lock)) {
|
|
||||||
if (lock->trx != trx) {
|
|
||||||
/* A lock on the table is held
|
|
||||||
by some other transaction. */
|
|
||||||
goto not_ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(lock_get_type_low(lock) & LOCK_TABLE)) {
|
|
||||||
/* We are interested in table locks only. */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (lock_get_mode(lock)) {
|
|
||||||
case LOCK_IX:
|
|
||||||
ok = TRUE;
|
|
||||||
break;
|
|
||||||
case LOCK_AUTO_INC:
|
|
||||||
/* It is allowed for trx to hold an
|
|
||||||
auto_increment lock. */
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
not_ok:
|
|
||||||
/* Other table locks than LOCK_IX are not allowed. */
|
|
||||||
ok = FALSE;
|
|
||||||
goto func_exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func_exit:
|
|
||||||
lock_mutex_exit();
|
|
||||||
|
|
||||||
return(ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
Sets the wait flag of a lock and the back pointer in trx to lock. */
|
Sets the wait flag of a lock and the back pointer in trx to lock. */
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
|
|
|
||||||
|
|
@ -3191,12 +3191,21 @@ row_ins_clust_index_entry(
|
||||||
|
|
||||||
n_uniq = dict_index_is_unique(index) ? index->n_uniq : 0;
|
n_uniq = dict_index_is_unique(index) ? index->n_uniq : 0;
|
||||||
|
|
||||||
/* Try first optimistic descent to the B-tree */
|
ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK
|
||||||
log_free_check();
|
|
||||||
const ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK
|
|
||||||
: dict_table_is_temporary(index->table)
|
: dict_table_is_temporary(index->table)
|
||||||
? BTR_NO_LOCKING_FLAG : 0;
|
? BTR_NO_LOCKING_FLAG : 0;
|
||||||
|
|
||||||
|
/* For intermediate table during copy alter table,
|
||||||
|
skip the undo log and record lock checking for
|
||||||
|
insertion operation.
|
||||||
|
*/
|
||||||
|
if (index->table->skip_alter_undo) {
|
||||||
|
flags |= BTR_NO_UNDO_LOG_FLAG | BTR_NO_LOCKING_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try first optimistic descent to the B-tree */
|
||||||
|
log_free_check();
|
||||||
|
|
||||||
err = row_ins_clust_index_entry_low(
|
err = row_ins_clust_index_entry_low(
|
||||||
flags, BTR_MODIFY_LEAF, index, n_uniq, entry,
|
flags, BTR_MODIFY_LEAF, index, n_uniq, entry,
|
||||||
n_ext, thr, dup_chk_only);
|
n_ext, thr, dup_chk_only);
|
||||||
|
|
@ -3239,6 +3248,7 @@ row_ins_sec_index_entry(
|
||||||
dberr_t err;
|
dberr_t err;
|
||||||
mem_heap_t* offsets_heap;
|
mem_heap_t* offsets_heap;
|
||||||
mem_heap_t* heap;
|
mem_heap_t* heap;
|
||||||
|
trx_id_t trx_id = 0;
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("row_ins_sec_index_entry_timeout", {
|
DBUG_EXECUTE_IF("row_ins_sec_index_entry_timeout", {
|
||||||
DBUG_SET("-d,row_ins_sec_index_entry_timeout");
|
DBUG_SET("-d,row_ins_sec_index_entry_timeout");
|
||||||
|
|
@ -3261,13 +3271,22 @@ row_ins_sec_index_entry(
|
||||||
/* Try first optimistic descent to the B-tree */
|
/* Try first optimistic descent to the B-tree */
|
||||||
|
|
||||||
log_free_check();
|
log_free_check();
|
||||||
const ulint flags = dict_table_is_temporary(index->table)
|
ulint flags = dict_table_is_temporary(index->table)
|
||||||
? BTR_NO_LOCKING_FLAG
|
? BTR_NO_LOCKING_FLAG
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
/* For intermediate table during copy alter table,
|
||||||
|
skip the undo log and record lock checking for
|
||||||
|
insertion operation.
|
||||||
|
*/
|
||||||
|
if (index->table->skip_alter_undo) {
|
||||||
|
trx_id = thr_get_trx(thr)->id;
|
||||||
|
flags |= BTR_NO_UNDO_LOG_FLAG | BTR_NO_LOCKING_FLAG;
|
||||||
|
}
|
||||||
|
|
||||||
err = row_ins_sec_index_entry_low(
|
err = row_ins_sec_index_entry_low(
|
||||||
flags, BTR_MODIFY_LEAF, index, offsets_heap, heap, entry,
|
flags, BTR_MODIFY_LEAF, index, offsets_heap, heap, entry,
|
||||||
0, thr, dup_chk_only);
|
trx_id, thr, dup_chk_only);
|
||||||
if (err == DB_FAIL) {
|
if (err == DB_FAIL) {
|
||||||
mem_heap_empty(heap);
|
mem_heap_empty(heap);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1260,20 +1260,11 @@ run_again:
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
/** Lock a table.
|
||||||
Sets a table lock on the table mentioned in prebuilt.
|
@param[in,out] prebuilt table handle
|
||||||
@return error code or DB_SUCCESS */
|
@return error code or DB_SUCCESS */
|
||||||
dberr_t
|
dberr_t
|
||||||
row_lock_table_for_mysql(
|
row_lock_table(row_prebuilt_t* prebuilt)
|
||||||
/*=====================*/
|
|
||||||
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct in the MySQL
|
|
||||||
table handle */
|
|
||||||
dict_table_t* table, /*!< in: table to lock, or NULL
|
|
||||||
if prebuilt->table should be
|
|
||||||
locked as
|
|
||||||
prebuilt->select_lock_type */
|
|
||||||
ulint mode) /*!< in: lock mode of table
|
|
||||||
(ignored if table==NULL) */
|
|
||||||
{
|
{
|
||||||
trx_t* trx = prebuilt->trx;
|
trx_t* trx = prebuilt->trx;
|
||||||
que_thr_t* thr;
|
que_thr_t* thr;
|
||||||
|
|
@ -1303,17 +1294,10 @@ run_again:
|
||||||
|
|
||||||
trx_start_if_not_started_xa(trx, false);
|
trx_start_if_not_started_xa(trx, false);
|
||||||
|
|
||||||
if (table) {
|
err = lock_table(0, prebuilt->table,
|
||||||
err = lock_table(
|
static_cast<enum lock_mode>(
|
||||||
0, table,
|
prebuilt->select_lock_type),
|
||||||
static_cast<enum lock_mode>(mode), thr);
|
thr);
|
||||||
} else {
|
|
||||||
err = lock_table(
|
|
||||||
0, prebuilt->table,
|
|
||||||
static_cast<enum lock_mode>(
|
|
||||||
prebuilt->select_lock_type),
|
|
||||||
thr);
|
|
||||||
}
|
|
||||||
|
|
||||||
trx->error_state = err;
|
trx->error_state = err;
|
||||||
|
|
||||||
|
|
@ -1552,9 +1536,21 @@ error_exit:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass NULL for the columns affected, since an INSERT affects
|
if (table->skip_alter_undo) {
|
||||||
all FTS indexes. */
|
if (trx->fts_trx == NULL) {
|
||||||
fts_trx_add_op(trx, table, doc_id, FTS_INSERT, NULL);
|
trx->fts_trx = fts_trx_create(trx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fts_trx_table_t ftt;
|
||||||
|
ftt.table = table;
|
||||||
|
ftt.fts_trx = trx->fts_trx;
|
||||||
|
|
||||||
|
fts_add_doc_from_tuple(&ftt, doc_id, node->row);
|
||||||
|
} else {
|
||||||
|
/* Pass NULL for the columns affected, since an INSERT affects
|
||||||
|
all FTS indexes. */
|
||||||
|
fts_trx_add_op(trx, table, doc_id, FTS_INSERT, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
que_thr_stop_for_mysql_no_error(thr, trx);
|
que_thr_stop_for_mysql_no_error(thr, trx);
|
||||||
|
|
|
||||||
|
|
@ -679,6 +679,7 @@ row_purge_upd_exist_or_extern_func(
|
||||||
mem_heap_t* heap;
|
mem_heap_t* heap;
|
||||||
|
|
||||||
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S));
|
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_S));
|
||||||
|
ut_ad(!node->table->skip_alter_undo);
|
||||||
|
|
||||||
if (node->rec_type == TRX_UNDO_UPD_DEL_REC
|
if (node->rec_type == TRX_UNDO_UPD_DEL_REC
|
||||||
|| (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
|
|| (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
|
||||||
|
|
@ -945,6 +946,7 @@ row_purge_record_func(
|
||||||
bool purged = true;
|
bool purged = true;
|
||||||
|
|
||||||
ut_ad(!node->found_clust);
|
ut_ad(!node->found_clust);
|
||||||
|
ut_ad(!node->table->skip_alter_undo);
|
||||||
|
|
||||||
clust_index = dict_table_get_first_index(node->table);
|
clust_index = dict_table_get_first_index(node->table);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -384,6 +384,7 @@ close_table:
|
||||||
dict_table_close(node->table, dict_locked, FALSE);
|
dict_table_close(node->table, dict_locked, FALSE);
|
||||||
node->table = NULL;
|
node->table = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
ut_ad(!node->table->skip_alter_undo);
|
||||||
clust_index = dict_table_get_first_index(node->table);
|
clust_index = dict_table_get_first_index(node->table);
|
||||||
|
|
||||||
if (clust_index != NULL) {
|
if (clust_index != NULL) {
|
||||||
|
|
|
||||||
|
|
@ -1145,6 +1145,8 @@ row_undo_mod_parse_undo_rec(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_ad(!node->table->skip_alter_undo);
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(!fil_table_accessible(node->table))) {
|
if (UNIV_UNLIKELY(!fil_table_accessible(node->table))) {
|
||||||
close_table:
|
close_table:
|
||||||
/* Normally, tables should not disappear or become
|
/* Normally, tables should not disappear or become
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,8 @@ row_undo_search_clust_to_pcur(
|
||||||
ulint* offsets = offsets_;
|
ulint* offsets = offsets_;
|
||||||
rec_offs_init(offsets_);
|
rec_offs_init(offsets_);
|
||||||
|
|
||||||
|
ut_ad(!node->table->skip_alter_undo);
|
||||||
|
|
||||||
mtr_start(&mtr);
|
mtr_start(&mtr);
|
||||||
|
|
||||||
clust_index = dict_table_get_first_index(node->table);
|
clust_index = dict_table_get_first_index(node->table);
|
||||||
|
|
|
||||||
|
|
@ -581,6 +581,7 @@ row_upd_changes_field_size_or_external(
|
||||||
ulint i;
|
ulint i;
|
||||||
|
|
||||||
ut_ad(rec_offs_validate(NULL, index, offsets));
|
ut_ad(rec_offs_validate(NULL, index, offsets));
|
||||||
|
ut_ad(!index->table->skip_alter_undo);
|
||||||
n_fields = upd_get_n_fields(update);
|
n_fields = upd_get_n_fields(update);
|
||||||
|
|
||||||
for (i = 0; i < n_fields; i++) {
|
for (i = 0; i < n_fields; i++) {
|
||||||
|
|
@ -695,6 +696,7 @@ row_upd_rec_in_place(
|
||||||
ulint i;
|
ulint i;
|
||||||
|
|
||||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||||
|
ut_ad(!index->table->skip_alter_undo);
|
||||||
|
|
||||||
if (rec_offs_comp(offsets)) {
|
if (rec_offs_comp(offsets)) {
|
||||||
rec_set_info_bits_new(rec, update->info_bits);
|
rec_set_info_bits_new(rec, update->info_bits);
|
||||||
|
|
@ -978,6 +980,7 @@ row_upd_build_sec_rec_difference_binary(
|
||||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||||
ut_ad(rec_offs_n_fields(offsets) == dtuple_get_n_fields(entry));
|
ut_ad(rec_offs_n_fields(offsets) == dtuple_get_n_fields(entry));
|
||||||
ut_ad(!rec_offs_any_extern(offsets));
|
ut_ad(!rec_offs_any_extern(offsets));
|
||||||
|
ut_ad(!index->table->skip_alter_undo);
|
||||||
|
|
||||||
update = upd_create(dtuple_get_n_fields(entry), heap);
|
update = upd_create(dtuple_get_n_fields(entry), heap);
|
||||||
|
|
||||||
|
|
@ -1059,6 +1062,7 @@ row_upd_build_difference_binary(
|
||||||
|
|
||||||
/* This function is used only for a clustered index */
|
/* This function is used only for a clustered index */
|
||||||
ut_a(dict_index_is_clust(index));
|
ut_a(dict_index_is_clust(index));
|
||||||
|
ut_ad(!index->table->skip_alter_undo);
|
||||||
|
|
||||||
update = upd_create(n_fld + n_v_fld, heap);
|
update = upd_create(n_fld + n_v_fld, heap);
|
||||||
|
|
||||||
|
|
@ -1330,6 +1334,8 @@ row_upd_index_replace_new_col_vals_index_pos(
|
||||||
mem_heap_t* heap) /*!< in: memory heap for allocating and
|
mem_heap_t* heap) /*!< in: memory heap for allocating and
|
||||||
copying the new values */
|
copying the new values */
|
||||||
{
|
{
|
||||||
|
ut_ad(!index->table->skip_alter_undo);
|
||||||
|
|
||||||
ulint i;
|
ulint i;
|
||||||
ulint n_fields;
|
ulint n_fields;
|
||||||
const page_size_t& page_size = dict_table_page_size(index->table);
|
const page_size_t& page_size = dict_table_page_size(index->table);
|
||||||
|
|
@ -1392,6 +1398,8 @@ row_upd_index_replace_new_col_vals(
|
||||||
= dict_table_get_first_index(index->table);
|
= dict_table_get_first_index(index->table);
|
||||||
const page_size_t& page_size = dict_table_page_size(index->table);
|
const page_size_t& page_size = dict_table_page_size(index->table);
|
||||||
|
|
||||||
|
ut_ad(!index->table->skip_alter_undo);
|
||||||
|
|
||||||
dtuple_set_info_bits(entry, update->info_bits);
|
dtuple_set_info_bits(entry, update->info_bits);
|
||||||
|
|
||||||
for (i = 0; i < dict_index_get_n_fields(index); i++) {
|
for (i = 0; i < dict_index_get_n_fields(index); i++) {
|
||||||
|
|
@ -1466,6 +1474,8 @@ row_upd_replace_vcol(
|
||||||
ulint i;
|
ulint i;
|
||||||
ulint n_cols;
|
ulint n_cols;
|
||||||
|
|
||||||
|
ut_ad(!table->skip_alter_undo);
|
||||||
|
|
||||||
n_cols = dtuple_get_n_v_fields(row);
|
n_cols = dtuple_get_n_v_fields(row);
|
||||||
for (col_no = 0; col_no < n_cols; col_no++) {
|
for (col_no = 0; col_no < n_cols; col_no++) {
|
||||||
dfield_t* dfield;
|
dfield_t* dfield;
|
||||||
|
|
@ -1687,6 +1697,7 @@ row_upd_changes_ord_field_binary_func(
|
||||||
ut_ad(thr);
|
ut_ad(thr);
|
||||||
ut_ad(thr->graph);
|
ut_ad(thr->graph);
|
||||||
ut_ad(thr->graph->trx);
|
ut_ad(thr->graph->trx);
|
||||||
|
ut_ad(!index->table->skip_alter_undo);
|
||||||
|
|
||||||
n_unique = dict_index_get_n_unique(index);
|
n_unique = dict_index_get_n_unique(index);
|
||||||
|
|
||||||
|
|
@ -1946,6 +1957,8 @@ row_upd_changes_doc_id(
|
||||||
dict_index_t* clust_index;
|
dict_index_t* clust_index;
|
||||||
fts_t* fts = table->fts;
|
fts_t* fts = table->fts;
|
||||||
|
|
||||||
|
ut_ad(!table->skip_alter_undo);
|
||||||
|
|
||||||
clust_index = dict_table_get_first_index(table);
|
clust_index = dict_table_get_first_index(table);
|
||||||
|
|
||||||
/* Convert from index-specific column number to table-global
|
/* Convert from index-specific column number to table-global
|
||||||
|
|
@ -1968,6 +1981,8 @@ row_upd_changes_fts_column(
|
||||||
dict_index_t* clust_index;
|
dict_index_t* clust_index;
|
||||||
fts_t* fts = table->fts;
|
fts_t* fts = table->fts;
|
||||||
|
|
||||||
|
ut_ad(!table->skip_alter_undo);
|
||||||
|
|
||||||
if (upd_fld_is_virtual_col(upd_field)) {
|
if (upd_fld_is_virtual_col(upd_field)) {
|
||||||
col_no = upd_field->field_no;
|
col_no = upd_field->field_no;
|
||||||
return(dict_table_is_fts_column(fts->indexes, col_no, true));
|
return(dict_table_is_fts_column(fts->indexes, col_no, true));
|
||||||
|
|
@ -2814,6 +2829,7 @@ row_upd_clust_rec(
|
||||||
ut_ad(node);
|
ut_ad(node);
|
||||||
ut_ad(dict_index_is_clust(index));
|
ut_ad(dict_index_is_clust(index));
|
||||||
ut_ad(!thr_get_trx(thr)->in_rollback);
|
ut_ad(!thr_get_trx(thr)->in_rollback);
|
||||||
|
ut_ad(!node->table->skip_alter_undo);
|
||||||
|
|
||||||
pcur = node->pcur;
|
pcur = node->pcur;
|
||||||
btr_cur = btr_pcur_get_btr_cur(pcur);
|
btr_cur = btr_pcur_get_btr_cur(pcur);
|
||||||
|
|
|
||||||
|
|
@ -2349,6 +2349,8 @@ trx_undo_prev_version_build(
|
||||||
const bool is_temp = dict_table_is_temporary(index->table);
|
const bool is_temp = dict_table_is_temporary(index->table);
|
||||||
rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
|
rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
|
||||||
|
|
||||||
|
ut_ad(!index->table->skip_alter_undo);
|
||||||
|
|
||||||
if (trx_undo_get_undo_rec(
|
if (trx_undo_get_undo_rec(
|
||||||
roll_ptr, is_temp, heap, rec_trx_id, index->table->name,
|
roll_ptr, is_temp, heap, rec_trx_id, index->table->name,
|
||||||
&undo_rec)) {
|
&undo_rec)) {
|
||||||
|
|
|
||||||
|
|
@ -541,6 +541,15 @@ static const char *mrn_inspect_extra_function(enum ha_extra_function operation)
|
||||||
case HA_EXTRA_DETACH_CHILDREN:
|
case HA_EXTRA_DETACH_CHILDREN:
|
||||||
inspected = "HA_EXTRA_DETACH_CHILDREN";
|
inspected = "HA_EXTRA_DETACH_CHILDREN";
|
||||||
break;
|
break;
|
||||||
|
case HA_EXTRA_BEGIN_ALTER_COPY:
|
||||||
|
inspected = "HA_EXTRA_BEGIN_ALTER_COPY";
|
||||||
|
break;
|
||||||
|
case HA_EXTRA_END_ALTER_COPY:
|
||||||
|
inspected = "HA_EXTRA_END_ALTER_COPY";
|
||||||
|
break;
|
||||||
|
case HA_EXTRA_FAKE_START_STMT:
|
||||||
|
inspected = "HA_EXTRA_FAKE_START_STMT";
|
||||||
|
break;
|
||||||
#ifdef MRN_HAVE_HA_EXTRA_EXPORT
|
#ifdef MRN_HAVE_HA_EXTRA_EXPORT
|
||||||
case HA_EXTRA_EXPORT:
|
case HA_EXTRA_EXPORT:
|
||||||
inspected = "HA_EXTRA_EXPORT";
|
inspected = "HA_EXTRA_EXPORT";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue