From ce28fa53032dd7c233ed4875514bf85eafec0bc4 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Thu, 24 Jan 2019 16:01:28 +0200 Subject: [PATCH 01/91] Backported wsrep-recover test from 10.4. Backported wsrep-recover test from 10.4 to test the wsrep recovery after database shutdown or crash. Renamed the test to wsrep-recover-v25 to avoid conflicts with existing test in 10.4 and to provide coverage for wsrep-API v25 compatible behavior. The test case in 10.2 is simpler because out of order prepare step cannot happen, the commit order critical section is grabbed before prepare phase. Test is not recorded since it does not produce expected result. --- .../suite/wsrep/t/wsrep-recover-step.inc | 41 ++++++ .../suite/wsrep/t/wsrep-recover-v25.cnf | 7 ++ .../wsrep/t/wsrep-recover-v25.combinations | 4 + .../suite/wsrep/t/wsrep-recover-v25.test | 119 ++++++++++++++++++ 4 files changed, 171 insertions(+) create mode 100644 mysql-test/suite/wsrep/t/wsrep-recover-step.inc create mode 100644 mysql-test/suite/wsrep/t/wsrep-recover-v25.cnf create mode 100644 mysql-test/suite/wsrep/t/wsrep-recover-v25.combinations create mode 100644 mysql-test/suite/wsrep/t/wsrep-recover-v25.test diff --git a/mysql-test/suite/wsrep/t/wsrep-recover-step.inc b/mysql-test/suite/wsrep/t/wsrep-recover-step.inc new file mode 100644 index 00000000000..22669438fe0 --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep-recover-step.inc @@ -0,0 +1,41 @@ +# +# Macro to run wsrep recovery step. This is adapted from +# suite/galera/include/galera_wsrep_recover.inc, with additional +# option to pass binlog argument to recovery command. The macro +# returns recovered position split in uuid and seqno parts. +# +# Arguments: +# +# wsrep_recover_binlog_opt - Binlog options to recovery command +# +# Return: +# +# wsrep_recover_start_position_uuid - UUID corresponding to recovered position +# wsrep_recover_start_position_seqno - seqno corresponding to recovered position +# + +--exec $MYSQLD --defaults-group-suffix=.1 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --log-error=$MYSQL_TMP_DIR/galera_wsrep_recover.log --innodb --wsrep-recover $wsrep_recover_binlog_opt --core-file > $MYSQL_TMP_DIR/galera_wsrep_recover.log 2>&1 + +--perl + use strict; + my $wsrep_start_position = `grep 'WSREP: Recovered position:' $ENV{MYSQL_TMP_DIR}/galera_wsrep_recover.log | sed 's/.*WSREP\:\ Recovered\ position://' | sed 's/^[ \t]*//'`; + chomp($wsrep_start_position); + die if $wsrep_start_position eq ''; + open(FILE, ">", "$ENV{MYSQL_TMP_DIR}/galera_wsrep_start_position.inc") or die; + my ($uuid, $seqno) = split /:/, $wsrep_start_position; + print FILE "--let \$wsrep_recover_start_position_uuid = $uuid\n"; + print FILE "--let \$wsrep_recover_start_position_seqno = $seqno\n"; + close FILE; +EOF + +--source $MYSQL_TMP_DIR/galera_wsrep_start_position.inc + +if ($wsrep_recover_start_position_uuid == '') { + --die "Could not obtain start_position_uuid." +} + +if ($wsrep_recover_start_position_seqno == '') { + --die "Could not obtain start_position_seqno." +} + +--remove_file $MYSQL_TMP_DIR/galera_wsrep_start_position.inc diff --git a/mysql-test/suite/wsrep/t/wsrep-recover-v25.cnf b/mysql-test/suite/wsrep/t/wsrep-recover-v25.cnf new file mode 100644 index 00000000000..b1c96d2614d --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep-recover-v25.cnf @@ -0,0 +1,7 @@ +!include ../my.cnf + +[mysqld.1] +wsrep-on=ON +wsrep-cluster-address=gcomm:// +wsrep-provider=@ENV.WSREP_PROVIDER +binlog-format=ROW diff --git a/mysql-test/suite/wsrep/t/wsrep-recover-v25.combinations b/mysql-test/suite/wsrep/t/wsrep-recover-v25.combinations new file mode 100644 index 00000000000..1ce3b45aa1a --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep-recover-v25.combinations @@ -0,0 +1,4 @@ +[binlogon] +log-bin + +[binlogoff] diff --git a/mysql-test/suite/wsrep/t/wsrep-recover-v25.test b/mysql-test/suite/wsrep/t/wsrep-recover-v25.test new file mode 100644 index 00000000000..cfd77fbdef4 --- /dev/null +++ b/mysql-test/suite/wsrep/t/wsrep-recover-v25.test @@ -0,0 +1,119 @@ +# +# Verify that the wsrep XID gets updated in InnoDB rollback segment +# properly and can be recovered with --wsrep-recover +# +# The test runs the following scenarios: +# +# 1) The server is started but no SQL is run +# 2) DDL is executed +# 3) INSERT is executed +# 4) Two INSERTs are executed so that the first one in order will be +# blocked after certification and the second one before entering +# commit order critical section. +# 5) Two DMLs are executed so that the prepare step is run out of order. +# Both transactions are blocked before commit order critical section. +# +# After each scenario server is killed and the recovered position +# is validated. +# + +--source include/have_wsrep.inc +--source include/have_innodb.inc +--source include/have_wsrep_provider.inc +--source include/have_debug_sync.inc + +# +# Binlog option for recovery run. This must be set in the test because +# combinations file causes log-bin option to be set from command line, +# not via my.cnf. +# +--let $log_bin = `SELECT @@log_bin` +if ($log_bin) { +--let $wsrep_recover_binlog_opt = --log-bin +} + +# +# Scenario 1 +# The expected recovered seqno is 1 corresponding to initial cluster +# configuration change. +# +--source include/kill_mysqld.inc +--source wsrep-recover-step.inc +--echo Expect seqno 0 +--echo $wsrep_recover_start_position_seqno + +--let $restart_parameters = --wsrep-start-position=$wsrep_recover_start_position_uuid:$wsrep_recover_start_position_seqno +--source include/start_mysqld.inc +--source include/wait_wsrep_ready.inc + +# +# Senario 2 +# The expected recovered seqno is 1 corresponding to CREATE TABLE +# + +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +--source include/kill_mysqld.inc +--source wsrep-recover-step.inc +--echo Expect seqno 1 +--echo $wsrep_recover_start_position_seqno + +--let $restart_parameters = --wsrep-start-position=$wsrep_recover_start_position_uuid:$wsrep_recover_start_position_seqno +--source include/start_mysqld.inc +--source include/wait_wsrep_ready.inc + +# +# Scenario 3 +# The expected recovered seqno is 2 corresponding to CREATE TABLE and INSERT. +# +# The expected wsrep_last_committed after the server is restarted is 2. +# + +INSERT INTO t1 VALUES (5); +--source include/kill_mysqld.inc +--source wsrep-recover-step.inc +--echo Expect seqno 2 +--echo $wsrep_recover_start_position_seqno +--let $restart_parameters = --wsrep-start-position=$wsrep_recover_start_position_uuid:$wsrep_recover_start_position_seqno +--source include/start_mysqld.inc +--source include/wait_wsrep_ready.inc + +SELECT VARIABLE_VALUE `expect 2` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; + +# +# Scenario 4 +# +# The INSERT gets prepared but not committed. +# +# If binlog is off, the expected outcome is that the INSERT gets committed +# since it is already committed in the cluster. If binlog is on, the INSERT +# should be rolled back during recovery phase since it has not yet +# been logged into binlog. +# +--connect con1, localhost, root +SET DEBUG_SYNC = "ha_commit_trans_after_prepare SIGNAL after_prepare_reached WAIT_FOR continue"; +--send INSERT INTO t1 VALUES (7) + +--connection default +SET DEBUG_SYNC = "now WAIT_FOR after_prepare_reached"; +--source include/kill_mysqld.inc +--source wsrep-recover-step.inc +if ($log_bin) { + --echo Expect seqno 2 +} +if (!$log_bin) { + --echo Expect seqno 3 +} +--echo $wsrep_recover_start_position_seqno +--let $restart_parameters = --wsrep-start-position=$wsrep_recover_start_position_uuid:$wsrep_recover_start_position_seqno +--source include/start_mysqld.inc +--source include/wait_wsrep_ready.inc + +if ($log_bin) { + --echo Expect 5 +} +if (!$log_bin) { + --echo Expect 5 7 +} +SELECT * FROM t1; + +DROP TABLE t1; From 040b840de7bcd32b0236531a7aec95b11341cef3 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Thu, 24 Jan 2019 16:31:33 +0200 Subject: [PATCH 02/91] MDEV-15740 Backport wsrep recovery fixes from 10.4. Clear wsrep XID in innobase_rollback_by_xid() for recovered wsrep transaction in order to avoid resetting XID storage when rolling back wsrep transaction during recovery. Sort wsrep XIDs read from storage engine in ascending order and erify that the range is continuous during crash recovery. If binlog is off, commit all recovered transactions for continuous seqno range. This is safe because all transactions with wsrep XID have been certified and must be committed in the cluster. On the other hand if binlog is on, respect binlog as a transaction coordinator in order to avoid missing transactions in binlog that have been committed into storage engine . --- sql/handler.cc | 51 +++++++++++++++++++++++++-- sql/wsrep_xid.cc | 34 ++++++++++++++++++ sql/wsrep_xid.h | 2 ++ storage/innobase/handler/ha_innodb.cc | 8 +++++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index da41daf2440..e2a8d16b723 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1827,6 +1827,35 @@ static char* xid_to_str(char *buf, XID *xid) } #endif +#ifdef WITH_WSREP +static my_xid wsrep_order_and_check_continuity(XID *list, int len) +{ + wsrep_sort_xid_array(list, len); + wsrep_uuid_t uuid; + wsrep_seqno_t seqno; + if (wsrep_get_SE_checkpoint(uuid, seqno)) + { + WSREP_ERROR("Could not read wsrep SE checkpoint for recovery"); + return 0; + } + long long cur_seqno= seqno; + for (int i= 0; i < len; ++i) + { + if (!wsrep_is_wsrep_xid(list + i) || + wsrep_xid_seqno(*(list + i)) != cur_seqno + 1) + { + WSREP_WARN("Discovered discontinuity in recovered wsrep " + "transaction XIDs. Truncating the recovery list to " + "%d entries", i); + break; + } + ++cur_seqno; + } + WSREP_INFO("Last wsrep seqno to be recovered %lld", cur_seqno); + return (cur_seqno < 0 ? 0 : cur_seqno); +} +#endif /* WITH_WSREP */ + /** recover() step of xa. @@ -1864,6 +1893,19 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, { sql_print_information("Found %d prepared transaction(s) in %s", got, hton_name(hton)->str); +#ifdef WITH_WSREP + /* If wsrep_on=ON, XIDs are first ordered and then the range of + recovered XIDs is checked for continuity. All the XIDs which + are in continuous range can be safely committed if binlog + is off since they have already ordered and certified in the + cluster. */ + my_xid wsrep_limit= 0; + if (WSREP_ON) + { + wsrep_limit= wsrep_order_and_check_continuity(info->list, got); + } +#endif /* WITH_WSREP */ + for (int i=0; i < got; i ++) { my_xid x= WSREP_ON && wsrep_is_wsrep_xid(&info->list[i]) ? @@ -1885,9 +1927,12 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, continue; } // recovery mode - if (info->commit_list ? - my_hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 : - tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT) + if (IF_WSREP((wsrep_emulate_bin_log && + wsrep_is_wsrep_xid(info->list + i) && + x <= wsrep_limit), false) || + (info->commit_list ? + my_hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 : + tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)) { #ifndef DBUG_OFF int rc= diff --git a/sql/wsrep_xid.cc b/sql/wsrep_xid.cc index c0b7669d8ca..72b96cadfb0 100644 --- a/sql/wsrep_xid.cc +++ b/sql/wsrep_xid.cc @@ -20,6 +20,8 @@ #include "sql_class.h" #include "wsrep_mysqld.h" // for logging macros +#include /* std::sort() */ + /* * WSREPXid */ @@ -154,3 +156,35 @@ bool wsrep_get_SE_checkpoint(wsrep_uuid_t& uuid, wsrep_seqno_t& seqno) return false; } + +/* + Sort order for XIDs. Wsrep XIDs are sorted according to + seqno in ascending order. Non-wsrep XIDs are considered + equal among themselves and greater than with respect + to wsrep XIDs. + */ +struct Wsrep_xid_cmp +{ + bool operator()(const XID& left, const XID& right) const + { + const bool left_is_wsrep= wsrep_is_wsrep_xid(&left); + const bool right_is_wsrep= wsrep_is_wsrep_xid(&right); + if (left_is_wsrep && right_is_wsrep) + { + return (wsrep_xid_seqno(left) < wsrep_xid_seqno(right)); + } + else if (left_is_wsrep) + { + return true; + } + else + { + return false; + } + } +}; + +void wsrep_sort_xid_array(XID *array, int len) +{ + std::sort(array, array + len, Wsrep_xid_cmp()); +} diff --git a/sql/wsrep_xid.h b/sql/wsrep_xid.h index 5b33a904de1..01b18506708 100644 --- a/sql/wsrep_xid.h +++ b/sql/wsrep_xid.h @@ -32,5 +32,7 @@ bool wsrep_get_SE_checkpoint(wsrep_uuid_t&, wsrep_seqno_t&); //void wsrep_set_SE_checkpoint(XID&); /* uncomment if needed */ bool wsrep_set_SE_checkpoint(const wsrep_uuid_t&, wsrep_seqno_t); +void wsrep_sort_xid_array(XID *array, int len); + #endif /* WITH_WSREP */ #endif /* WSREP_UTILS_H */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 3e68e2d1d4a..dde12e5c2d5 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -17260,6 +17260,14 @@ innobase_rollback_by_xid( } if (trx_t* trx = trx_get_trx_by_xid(xid)) { +#ifdef WITH_WSREP + /* If a wsrep transaction is being rolled back during + the recovery, we must clear the xid in order to avoid + writing serialisation history for rolled back transaction. */ + if (wsrep_is_wsrep_xid(trx->xid)) { + trx->xid->null(); + } +#endif /* WITH_WSREP */ int ret = innobase_rollback_trx(trx); trx_deregister_from_2pc(trx); ut_ad(!trx->will_lock); From 4ea128391b964fbad5b58629bdee980bbedbd228 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Thu, 24 Jan 2019 17:37:45 +0200 Subject: [PATCH 03/91] MDEV-15740 Fix wsrep recovery with wsrep_emulate_bin_log If the TC log did not provide list of XIDs to recover, the commit by XID was skipped during wsrep recovery if binlog emulation was on. However, with wsrep we want to commit every prepared transaction with assigned wsrep XID since the transaction has already been committed in the cluster. Added a special condition to always proceed to commit by XID in xarecover_handlerton() if binlog is off and the recovered transaction has wsrep XID. --- sql/handler.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sql/handler.cc b/sql/handler.cc index e2a8d16b723..a9688fb96b4 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1921,7 +1921,10 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, info->found_foreign_xids++; continue; } - if (info->dry_run) + if (IF_WSREP(!(wsrep_emulate_bin_log && + wsrep_is_wsrep_xid(info->list + i) && + x <= wsrep_limit) && info->dry_run, + info->dry_run)) { info->found_my_xids++; continue; From ddfc789098e7f038e1f8f62f79663d9751b957c2 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Sun, 27 Jan 2019 15:44:35 +0200 Subject: [PATCH 04/91] MDEV-15740 Recorded wsrep-recover-v25 --- .../wsrep/r/wsrep-recover-v25,binlogon.rdiff | 17 +++++++++++ .../suite/wsrep/r/wsrep-recover-v25.result | 28 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 mysql-test/suite/wsrep/r/wsrep-recover-v25,binlogon.rdiff create mode 100644 mysql-test/suite/wsrep/r/wsrep-recover-v25.result diff --git a/mysql-test/suite/wsrep/r/wsrep-recover-v25,binlogon.rdiff b/mysql-test/suite/wsrep/r/wsrep-recover-v25,binlogon.rdiff new file mode 100644 index 00000000000..5bf6502d0d8 --- /dev/null +++ b/mysql-test/suite/wsrep/r/wsrep-recover-v25,binlogon.rdiff @@ -0,0 +1,17 @@ +--- r/wsrep-recover-v25.result 2019-01-27 15:38:58.819204748 +0200 ++++ r/wsrep-recover-v25.reject 2019-01-27 15:39:49.967358994 +0200 +@@ -18,11 +18,10 @@ + connection default; + SET DEBUG_SYNC = "now WAIT_FOR after_prepare_reached"; + # Kill the server +-Expect seqno 3 +-3 +-Expect 5 7 ++Expect seqno 2 ++2 ++Expect 5 + SELECT * FROM t1; + f1 + 5 +-7 + DROP TABLE t1; diff --git a/mysql-test/suite/wsrep/r/wsrep-recover-v25.result b/mysql-test/suite/wsrep/r/wsrep-recover-v25.result new file mode 100644 index 00000000000..6d146f67bdf --- /dev/null +++ b/mysql-test/suite/wsrep/r/wsrep-recover-v25.result @@ -0,0 +1,28 @@ +# Kill the server +Expect seqno 0 +0 +CREATE TABLE t1 (f1 INT PRIMARY KEY) ENGINE=InnoDB; +# Kill the server +Expect seqno 1 +1 +INSERT INTO t1 VALUES (5); +# Kill the server +Expect seqno 2 +2 +SELECT VARIABLE_VALUE `expect 2` FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'; +expect 2 +2 +connect con1, localhost, root; +SET DEBUG_SYNC = "ha_commit_trans_after_prepare SIGNAL after_prepare_reached WAIT_FOR continue"; +INSERT INTO t1 VALUES (7); +connection default; +SET DEBUG_SYNC = "now WAIT_FOR after_prepare_reached"; +# Kill the server +Expect seqno 3 +3 +Expect 5 7 +SELECT * FROM t1; +f1 +5 +7 +DROP TABLE t1; From 4ef556955f5083ff046a195b3d0a68545224483e Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Thu, 24 Jan 2019 17:42:30 +0200 Subject: [PATCH 05/91] MDEV-15740 Enabled and recorded galera_gcache_recover_manytrx --- mysql-test/suite/galera/disabled.def | 1 - .../r/galera_gcache_recover_manytrx.result | 29 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 9a8adba7a03..4dcfdec84ce 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -44,4 +44,3 @@ galera.MW-328C : MDEV-17847 Galera test failure on MW-328[A|B|C] galera.galera_sst_xtrabackup-v2 : MDEV-17848 Galera test failure on galera_sst_xtrabackup-v2[_data_dir] galera.galera_sst_xtrabackup-v2_data_dir : MDEV-17848 Galera test failure on galera_sst_xtrabackup-v2[_data_dir] query_cache : MDEV-18137: Galera test failure on query_cache -galera_gcache_recover_manytrx : MDEV-15740 diff --git a/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result b/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result index 868b39bfbd6..604b24a8fab 100644 --- a/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result +++ b/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result @@ -70,28 +70,55 @@ WHILE 1 DO INSERT INTO t1 (f2) VALUES (REPEAT('x', 1024 * 1024 * 10)); END WHILE; END| +connect node_1_insert_simple, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_1_insert_multi, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_1_insert_transaction, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_1_update_simple, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_1_insert_1k, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_1_insert_1m, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connect node_1_insert_10m, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1_insert_simple; CALL insert_simple();; +connection node_1_insert_multi; CALL insert_multi();; +connection node_1_insert_transaction; CALL insert_transaction ();; +connection node_1_update_simple; CALL update_simple ();; +connection node_1_insert_1k; CALL insert_1k ();; +connection node_1_insert_1m; CALL insert_1m ();; +connection node_1_insert_10m; CALL insert_10m ();; +connection node_2; SET SESSION wsrep_sync_wait = 0; Killing server ... +connection node_1; Killing server ... +connection node_1_insert_simple; ERROR HY000: Lost connection to MySQL server during query +connection node_1_insert_multi; ERROR HY000: Lost connection to MySQL server during query +connection node_1_insert_transaction; ERROR HY000: Lost connection to MySQL server during query +connection node_1_update_simple; ERROR HY000: Lost connection to MySQL server during query +connection node_1_insert_1k; ERROR HY000: Lost connection to MySQL server during query +connection node_1_insert_1m; ERROR HY000: Lost connection to MySQL server during query +connection node_1_insert_10m; ERROR HY000: Lost connection to MySQL server during query +connection node_1; Performing --wsrep-recover ... Using --wsrep-start-position when starting mysqld ... +connection node_2; Performing --wsrep-recover ... Using --wsrep-start-position when starting mysqld ... +connection node_1; include/diff_servers.inc [servers=1 2] +connection node_1; DROP TABLE t1; DROP TABLE ten; DROP PROCEDURE insert_simple; @@ -100,8 +127,10 @@ DROP PROCEDURE insert_transaction; DROP PROCEDURE update_simple; DROP PROCEDURE insert_1k; DROP PROCEDURE insert_1m; +connection node_1; CALL mtr.add_suppression("conflict state 7 after post commit"); CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); include/assert_grep.inc [async IST sender starting to serve] +connection node_2; CALL mtr.add_suppression("Skipped GCache ring buffer recovery"); include/assert_grep.inc [Recovering GCache ring buffer: found gapless sequence] From 36be0a5aef0376c526d68007da1c11ac440f0d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 28 Jan 2019 17:58:14 +0200 Subject: [PATCH 06/91] MDEV-18399 Recognize the deprecated parameters innodb_file_format, innodb_large_prefix The parameters innodb_file_format and innodb_large_prefix were overridden in the Debian-distributed configuration files, because the default values of these parameters between MariaDB 5.5 and MariaDB 10.2 did not make any sense. To allow a more seamless upgrade from MariaDB 10.1 to later versions, let InnoDB recognize the parameters innodb_file_format and innodb_large_prefix and issue deprecation warnings for them if they are specified. A deprecation period of only one major release (one year between the MariaDB 10.2 and 10.3 releases) is insufficient for these widely used parameters. --- .../r/prefix_index_liftedlimit.result | 2 +- .../t/prefix_index_liftedlimit.test | 2 +- .../suite/sys_vars/r/sysvars_innodb.result | 28 +++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 25 +++++++++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb_zip/r/prefix_index_liftedlimit.result b/mysql-test/suite/innodb_zip/r/prefix_index_liftedlimit.result index 7a73dae473e..96e51e506f2 100644 --- a/mysql-test/suite/innodb_zip/r/prefix_index_liftedlimit.result +++ b/mysql-test/suite/innodb_zip/r/prefix_index_liftedlimit.result @@ -1388,7 +1388,7 @@ ALTER TABLE worklog5743 ADD PRIMARY KEY `pk_idx` (col_1_varchar(3000)); ERROR 23000: Duplicate entry 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' for key 'PRIMARY' DROP TABLE worklog5743; set global innodb_large_prefix=0; -ERROR HY000: Unknown system variable 'innodb_large_prefix' +ERROR HY000: Variable 'innodb_large_prefix' is a read only variable CREATE TABLE worklog5743 ( col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) , PRIMARY KEY (col_1_varchar(3072)) diff --git a/mysql-test/suite/innodb_zip/t/prefix_index_liftedlimit.test b/mysql-test/suite/innodb_zip/t/prefix_index_liftedlimit.test index 5a944f0ae8b..bca710386d0 100644 --- a/mysql-test/suite/innodb_zip/t/prefix_index_liftedlimit.test +++ b/mysql-test/suite/innodb_zip/t/prefix_index_liftedlimit.test @@ -1300,7 +1300,7 @@ ALTER TABLE worklog5743 ADD PRIMARY KEY `pk_idx` (col_1_varchar(3000)); DROP TABLE worklog5743; # ----------------------------------------------------------------------------- ---error ER_UNKNOWN_SYSTEM_VARIABLE +--error ER_INCORRECT_GLOBAL_LOCAL_VAR set global innodb_large_prefix=0; CREATE TABLE worklog5743 ( col_1_varchar VARCHAR (4000) , col_2_varchar VARCHAR (4000) , diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index a6f626dd0b5..22105923764 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -904,6 +904,20 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME INNODB_FILE_FORMAT +SESSION_VALUE NULL +GLOBAL_VALUE +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Deprecated parameter with no effect. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME INNODB_FILE_PER_TABLE SESSION_VALUE NULL GLOBAL_VALUE ON @@ -1296,6 +1310,20 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME INNODB_LARGE_PREFIX +SESSION_VALUE NULL +GLOBAL_VALUE +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE VARCHAR +VARIABLE_COMMENT Deprecated parameter with no effect. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NULL +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME INNODB_LIMIT_OPTIMISTIC_INSERT_DEBUG SESSION_VALUE NULL GLOBAL_VALUE 0 diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0311b0400e6..7ccf296533a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -206,6 +206,11 @@ static char* innobase_reset_all_monitor_counter; static ulong innodb_flush_method; +/** Deprecated; no effect other than issuing a deprecation warning. */ +static char* innodb_file_format; +/** Deprecated; no effect other than issuing a deprecation warning. */ +static char* innodb_large_prefix; + /* This variable can be set in the server configure file, specifying stopword table to be used */ static char* innobase_server_stopword_table; @@ -3705,6 +3710,17 @@ static int innodb_init_params() char *default_path; ulong num_pll_degree; + if (innodb_large_prefix || innodb_file_format) { + const char* p = innodb_file_format + ? "file_format" + : "large_prefix"; + sql_print_warning("The parameter innodb_%s is deprecated" + " and has no effect." + " It may be removed in future releases." + " See https://mariadb.com/kb/en/library/" + "xtradbinnodb-file-format/", p); + } + /* Check that values don't overflow on 32-bit systems. */ if (sizeof(ulint) == 4) { if (innobase_buffer_pool_size > UINT_MAX32) { @@ -18989,6 +19005,13 @@ static MYSQL_SYSVAR_ENUM(flush_method, innodb_flush_method, NULL, NULL, IF_WIN(SRV_ALL_O_DIRECT_FSYNC, SRV_FSYNC), &innodb_flush_method_typelib); +static MYSQL_SYSVAR_STR(file_format, innodb_file_format, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Deprecated parameter with no effect.", NULL, NULL, NULL); +static MYSQL_SYSVAR_STR(large_prefix, innodb_large_prefix, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Deprecated parameter with no effect.", NULL, NULL, NULL); + static MYSQL_SYSVAR_BOOL(force_load_corrupted, srv_load_corrupted, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, "Force InnoDB to load metadata of corrupted table.", @@ -20033,6 +20056,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(read_io_threads), MYSQL_SYSVAR(write_io_threads), MYSQL_SYSVAR(file_per_table), + MYSQL_SYSVAR(file_format), /* deprecated in MariaDB 10.2; no effect */ MYSQL_SYSVAR(flush_log_at_timeout), MYSQL_SYSVAR(flush_log_at_trx_commit), MYSQL_SYSVAR(flush_method), @@ -20046,6 +20070,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(ft_min_token_size), MYSQL_SYSVAR(ft_num_word_optimize), MYSQL_SYSVAR(ft_sort_pll_degree), + MYSQL_SYSVAR(large_prefix), /* deprecated in MariaDB 10.2; no effect */ MYSQL_SYSVAR(force_load_corrupted), MYSQL_SYSVAR(lock_schedule_algorithm), MYSQL_SYSVAR(locks_unsafe_for_binlog), From b8aef87221c46c82921377f18a6498a31f7e5367 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 30 Jan 2019 15:32:51 +0530 Subject: [PATCH 07/91] MDEV-16849 Extending indexed VARCHAR column should be instantaneous Analysis: ======== Increasing the length of the indexed varchar column is not an instant operation for innodb. Fix: === - Introduce the new handler flag 'Alter_inplace_info::ALTER_COLUMN_INDEX_LENGTH' to indicate the index length differs due to change of column length changes. - InnoDB makes the ALTER_COLUMN_INDEX_LENGTH flag as instant operation. This is a port of Mysql fix. commit 913071c0b16cc03e703308250d795bc381627e37 Author: Nisha Gopalakrishnan Date: Wed May 30 14:54:46 2018 +0530 BUG#26848813: INDEXED COLUMN CAN'T BE CHANGED FROM VARCHAR(15) TO VARCHAR(40) INSTANTANEOUSLY --- .../innodb/r/alter_varchar_change.result | 461 ++++++++++++++++++ .../suite/innodb/t/alter_varchar_change.test | 336 +++++++++++++ sql/handler.h | 5 + sql/sql_table.cc | 41 +- storage/innobase/handler/handler0alter.cc | 3 +- 5 files changed, 834 insertions(+), 12 deletions(-) create mode 100644 mysql-test/suite/innodb/r/alter_varchar_change.result create mode 100644 mysql-test/suite/innodb/t/alter_varchar_change.test diff --git a/mysql-test/suite/innodb/r/alter_varchar_change.result b/mysql-test/suite/innodb/r/alter_varchar_change.result new file mode 100644 index 00000000000..0b06fddd35e --- /dev/null +++ b/mysql-test/suite/innodb/r/alter_varchar_change.result @@ -0,0 +1,461 @@ +CREATE PROCEDURE get_index_id(IN tbl_id INT, IN idx_name char(100), OUT idx_id INT) +BEGIN +SELECT index_id into idx_id FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE +NAME=idx_name and TABLE_ID=tbl_id; +END| +CREATE PROCEDURE get_table_id(IN tbl_name char(100), OUT tbl_id INT) +BEGIN +SELECT table_id into tbl_id FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE +NAME = tbl_name; +END| +SET @tbl_id = 0; +SET @tbl1_id = 0; +SET @idx_id = 0; +SET @idx1_id = 0; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200); +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) NOT NULL, + PRIMARY KEY (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200); +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + KEY `idx` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), f3 VARCHAR(100), +INDEX idx(f2, f3), index idx1(f3, f2))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), MODIFY f3 VARCHAR(150); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SELECT @idx1_id = @idx_id; +@idx1_id = @idx_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + `f3` varchar(150) DEFAULT NULL, + KEY `idx` (`f2`,`f3`), + KEY `idx1` (`f3`,`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), +INDEX idx(f2(40)))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SELECT @idx1_id = @idx_id; +@idx1_id = @idx_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + KEY `idx` (`f2`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), FULLTEXT idx(f2))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SELECT @idx1_id = @idx_id; +@idx1_id = @idx_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + FULLTEXT KEY `idx` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +f3 VARCHAR(50) as (f2) VIRTUAL, +INDEX idx(f3))ENGINE=InnoDB; +INSERT INTO t1(f1, f2) VALUES(1, repeat('a', 40)); +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(100); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SELECT @idx1_id = @idx_id; +@idx1_id = @idx_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(100) DEFAULT NULL, + `f3` varchar(50) GENERATED ALWAYS AS (`f2`) VIRTUAL, + KEY `idx` (`f3`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2(10)), +INDEX idx1(f1))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx1; +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SELECT @idx1_id = @idx_id; +@idx1_id = @idx_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + KEY `idx` (`f2`(10)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2(10)))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(10)); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SELECT @idx1_id = @idx_id; +@idx1_id = @idx_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + KEY `idx` (`f2`(10)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2(10)))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(50)); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SELECT @idx1_id = @idx_id; +@idx1_id = @idx_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + KEY `idx` (`f2`(50)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2(100)))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD INDEX idx1(f1); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SELECT @idx1_id = @idx_id; +@idx1_id = @idx_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + KEY `idx` (`f2`), + KEY `idx1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2(10)))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(6)); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SELECT @idx1_id = @idx_id; +@idx1_id = @idx_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + KEY `idx` (`f2`(6)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT; +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + `f3` int(11) DEFAULT NULL, + KEY `idx` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT; +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) NOT NULL, + `f3` int(11) DEFAULT NULL, + PRIMARY KEY (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100))ENGINE=INNODB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD FULLTEXT idx(f2); +Warnings: +Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) DEFAULT NULL, + FULLTEXT KEY `idx` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 CHAR(100) PRIMARY KEY)ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 CHAR(200); +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` char(200) NOT NULL, + PRIMARY KEY (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2(10)), +INDEX idx1(f1))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(50); +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(50) DEFAULT NULL, + KEY `idx` (`f2`(10)), + KEY `idx1` (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2(10)), +INDEX idx1(f1))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(5), DROP INDEX idx1; +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(5) DEFAULT NULL, + KEY `idx` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), FULLTEXT idx(f2))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(50); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SELECT @idx1_id = @idx_id; +@idx1_id = @idx_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(50) DEFAULT NULL, + FULLTEXT KEY `idx` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 CHAR(200); +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` char(200) DEFAULT NULL, + KEY `idx` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2(40)))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 TEXT; +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` text DEFAULT NULL, + KEY `idx` (`f2`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2(40)))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(300); +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(300) DEFAULT NULL, + KEY `idx` (`f2`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +INDEX idx(f2(40)))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200) CHARACTER SET UTF16; +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +0 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(200) CHARACTER SET utf16 DEFAULT NULL, + KEY `idx` (`f2`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(100), +f3 VARCHAR(50) as (f2) VIRTUAL, +INDEX idx(f3))ENGINE=InnoDB; +# If varchar virtual column extension is allowed in the future then +# InnoDB must rebuild the index +ALTER TABLE t1 MODIFY f3 VARCHAR(100); +ERROR HY000: This is not yet supported for generated columns +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(100) DEFAULT NULL, + `f3` varchar(50) GENERATED ALWAYS AS (`f2`) VIRTUAL, + KEY `idx` (`f3`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +DROP PROCEDURE get_index_id; +DROP PROCEDURE get_table_id; diff --git a/mysql-test/suite/innodb/t/alter_varchar_change.test b/mysql-test/suite/innodb/t/alter_varchar_change.test new file mode 100644 index 00000000000..f435125e581 --- /dev/null +++ b/mysql-test/suite/innodb/t/alter_varchar_change.test @@ -0,0 +1,336 @@ +--source include/have_innodb.inc + +DELIMITER |; +CREATE PROCEDURE get_index_id(IN tbl_id INT, IN idx_name char(100), OUT idx_id INT) +BEGIN +SELECT index_id into idx_id FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE + NAME=idx_name and TABLE_ID=tbl_id; +END| + +CREATE PROCEDURE get_table_id(IN tbl_name char(100), OUT tbl_id INT) +BEGIN +SELECT table_id into tbl_id FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE + NAME = tbl_name; +END| + +DELIMITER ;| + +SET @tbl_id = 0; +SET @tbl1_id = 0; +SET @idx_id = 0; +SET @idx1_id = 0; + +# Table should avoid rebuild for the following varchar change. + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200); +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +# Index should avoid rebuild +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200); +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), f3 VARCHAR(100), + INDEX idx(f2, f3), index idx1(f3, f2))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), MODIFY f3 VARCHAR(150); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); + +SELECT @tbl1_id = @tbl_id; +SELECT @idx1_id = @idx_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), + INDEX idx(f2(40)))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); + +SELECT @tbl1_id = @tbl_id; +SELECT @idx1_id = @idx_id; + +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), FULLTEXT idx(f2))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); + +SELECT @tbl1_id = @tbl_id; +SELECT @idx1_id = @idx_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + f3 VARCHAR(50) as (f2) VIRTUAL, + INDEX idx(f3))ENGINE=InnoDB; + +INSERT INTO t1(f1, f2) VALUES(1, repeat('a', 40)); + +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(100); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); + +SELECT @tbl1_id = @tbl_id; +SELECT @idx1_id = @idx_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2(10)), + INDEX idx1(f1))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx1; +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); + +SELECT @tbl1_id = @tbl_id; +SELECT @idx1_id = @idx_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2(10)))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(10)); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); + +SELECT @tbl1_id = @tbl_id; +SELECT @idx1_id = @idx_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2(10)))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(50)); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); + +SELECT @tbl1_id = @tbl_id; +SELECT @idx1_id = @idx_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +# Newly added index should built + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2(100)))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD INDEX idx1(f1); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); + +SELECT @tbl1_id = @tbl_id; +SELECT @idx1_id = @idx_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2(10)))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(6)); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); + +SELECT @tbl1_id = @tbl_id; +SELECT @idx1_id = @idx_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +# Table should rebuild + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT; +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT; +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100))ENGINE=INNODB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD FULLTEXT idx(f2); +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 CHAR(100) PRIMARY KEY)ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 CHAR(200); +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2(10)), + INDEX idx1(f1))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(50); +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2(10)), + INDEX idx1(f1))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(5), DROP INDEX idx1; +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), FULLTEXT idx(f2))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +CALL get_index_id(@tbl_id, "idx", @idx_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(50); +CALL get_table_id("test/t1", @tbl1_id); +CALL get_index_id(@tbl1_id, "idx", @idx1_id); + +SELECT @tbl1_id = @tbl_id; +SELECT @idx1_id = @idx_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 CHAR(200); +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2(40)))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 TEXT; +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2(40)))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(300); +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + INDEX idx(f2(40)))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(200) CHARACTER SET UTF16; +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; +# Show error when virtual varchar column got changed + +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(100), + f3 VARCHAR(50) as (f2) VIRTUAL, + INDEX idx(f3))ENGINE=InnoDB; + +--echo # If varchar virtual column extension is allowed in the future then +--echo # InnoDB must rebuild the index + +--error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN +ALTER TABLE t1 MODIFY f3 VARCHAR(100); +SHOW CREATE TABLE t1; +DROP TABLE t1; + +DROP PROCEDURE get_index_id; +DROP PROCEDURE get_table_id; diff --git a/sql/handler.h b/sql/handler.h index 284fed7cd7e..229197a2c78 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2001,6 +2001,11 @@ public: static const HA_ALTER_FLAGS ALTER_DROP_CHECK_CONSTRAINT= 1ULL << 40; + /** + Change in index length such that it doesn't require index rebuild. + */ + static const HA_ALTER_FLAGS ALTER_COLUMN_INDEX_LENGTH= 1ULL << 41; + /** Create options (like MAX_ROWS) for the new version of table. diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1b426f80a88..19100aafd51 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6303,7 +6303,7 @@ static bool fill_alter_inplace_info(THD *thd, bool varchar, Alter_inplace_info *ha_alter_info) { - Field **f_ptr, *field; + Field **f_ptr, *field, *old_field; List_iterator_fast new_field_it; Create_field *new_field; KEY_PART_INFO *key_part, *new_part; @@ -6629,6 +6629,7 @@ static bool fill_alter_inplace_info(THD *thd, Go through keys and check if the original ones are compatible with new table. */ + uint old_field_len= 0; KEY *table_key; KEY *table_key_end= table->key_info + table->s->keys; KEY *new_key; @@ -6693,17 +6694,35 @@ static bool fill_alter_inplace_info(THD *thd, key_part < end; key_part++, new_part++) { - /* - Key definition has changed if we are using a different field or - if the used key part length is different. It makes sense to - check lengths first as in case when fields differ it is likely - that lengths differ too and checking fields is more expensive - in general case. - */ - if (key_part->length != new_part->length) - goto index_changed; - new_field= get_field_by_index(alter_info, new_part->fieldnr); + old_field= table->field[key_part->fieldnr - 1]; + /* + If there is a change in index length due to column expansion + like varchar(X) changed to varchar(X + N) and has a compatible + packed data representation, we mark it for fast/INPLACE change + in index definition. InnoDB supports INPLACE for this cases + + Key definition has changed if we are using a different field or + if the user key part length is different. + */ + old_field_len= old_field->pack_length(); + + if (old_field->type() == MYSQL_TYPE_VARCHAR) + { + old_field_len= (old_field->pack_length() + - ((Field_varstring*) old_field)->length_bytes); + } + + if (key_part->length == old_field_len && + key_part->length < new_part->length && + (key_part->field->is_equal((Create_field*) new_field) + == IS_EQUAL_PACK_LENGTH)) + { + ha_alter_info->handler_flags |= + Alter_inplace_info::ALTER_COLUMN_INDEX_LENGTH; + } + else if (key_part->length != new_part->length) + goto index_changed; /* For prefix keys KEY_PART_INFO::field points to cloned Field diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 0f896e6138f..13d78d636d8 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -90,7 +90,8 @@ static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_INPLACE_IGNORE | Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT | Alter_inplace_info::ALTER_COLUMN_STORAGE_TYPE | Alter_inplace_info::ALTER_VIRTUAL_GCOL_EXPR - | Alter_inplace_info::ALTER_RENAME; + | Alter_inplace_info::ALTER_RENAME + | Alter_inplace_info::ALTER_COLUMN_INDEX_LENGTH; /** Operations on foreign key definitions (changing the schema only) */ static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_FOREIGN_OPERATIONS From c9f0a4a9bf52dedb229c7b12eee05db2b08a0289 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Wed, 30 Jan 2019 15:16:36 +0100 Subject: [PATCH 08/91] MDEV-18426: Most of the mtr tests in the galera_3nodes suite fail Most of the mtr tests in the galera_3nodes suite fail for a variety of reasons with a variety of errors. Some tests simply need to add the missing "connection" lines to the result files, but many of them fail due to substantial errors that require reworking test files. This patch adds the missing "connection" lines to the result files and fixes several substantial flaws in the galera_3nodes suite tests and in the mtr framework service files, adapting the tests from galera_3nodes for the current version of MariaDB. https://jira.mariadb.org/browse/MDEV-18426 --- .../galera => }/include/galera_resume.inc | 2 +- .../include/galera_suspend.inc | 2 +- mysql-test/include/mtr_check.sql | 1 + .../r/galera_evs_suspect_timeout.result | 6 ++++ .../suite/galera_3nodes/r/galera_garbd.result | 8 +++++ .../r/galera_ist_gcache_rollover.result | 1 + .../r/galera_pc_bootstrap.result | 11 +++++++ .../galera_3nodes/r/galera_pc_weight.result | 13 ++++++++ .../r/galera_safe_to_bootstrap.result | 27 ++++++++++++++++ .../r/galera_var_dirty_reads2.result | 5 +++ .../t/galera_evs_suspect_timeout.test | 2 +- .../suite/galera_3nodes/t/galera_garbd.test | 8 +++-- .../t/galera_ist_gcache_rollover.cnf | 6 ++-- .../t/galera_ist_gcache_rollover.test | 1 + .../t/galera_safe_to_bootstrap.test | 32 ++++++++++++++++--- 15 files changed, 112 insertions(+), 13 deletions(-) rename mysql-test/{suite/galera => }/include/galera_resume.inc (80%) rename mysql-test/{suite/galera_3nodes => }/include/galera_suspend.inc (86%) diff --git a/mysql-test/suite/galera/include/galera_resume.inc b/mysql-test/include/galera_resume.inc similarity index 80% rename from mysql-test/suite/galera/include/galera_resume.inc rename to mysql-test/include/galera_resume.inc index 232cb46479e..af8f2b956fd 100644 --- a/mysql-test/suite/galera/include/galera_resume.inc +++ b/mysql-test/include/galera_resume.inc @@ -3,7 +3,7 @@ my $pid_filename = $ENV{'_SUSPEND_NODE_PIDFILE'}; my $mysqld_pid = `cat $pid_filename`; chomp($mysqld_pid); - system("kill -18 $mysqld_pid"); + system("kill -SIGCONT $mysqld_pid"); exit(0); EOF diff --git a/mysql-test/suite/galera_3nodes/include/galera_suspend.inc b/mysql-test/include/galera_suspend.inc similarity index 86% rename from mysql-test/suite/galera_3nodes/include/galera_suspend.inc rename to mysql-test/include/galera_suspend.inc index 3495ad2342b..d4037d8958c 100644 --- a/mysql-test/suite/galera_3nodes/include/galera_suspend.inc +++ b/mysql-test/include/galera_suspend.inc @@ -9,6 +9,6 @@ my $pid_filename = $ENV{'_SUSPEND_NODE_PIDFILE'}; my $mysqld_pid = `cat $pid_filename`; chomp($mysqld_pid); - system("kill -19 $mysqld_pid"); + system("kill -SIGSTOP $mysqld_pid"); exit(0); EOF diff --git a/mysql-test/include/mtr_check.sql b/mysql-test/include/mtr_check.sql index f2c0b70e192..9f29222c969 100644 --- a/mysql-test/include/mtr_check.sql +++ b/mysql-test/include/mtr_check.sql @@ -35,6 +35,7 @@ BEGIN AND variable_name != 'INNODB_BUFFER_POOL_LOAD_AT_STARTUP' AND variable_name not like 'GTID%POS' AND variable_name != 'GTID_BINLOG_STATE' + AND variable_name != 'AUTO_INCREMENT_INCREMENT' ORDER BY variable_name; -- Dump all databases, there should be none diff --git a/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result b/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result index 7e0d282ec7f..6a7eea94077 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result +++ b/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result @@ -1,12 +1,17 @@ +connection node_1; SET GLOBAL wsrep_provider_options = 'evs.inactive_timeout=PT100M; evs.suspect_timeout=PT1S'; +connection node_2; SET GLOBAL wsrep_provider_options = 'evs.inactive_timeout=PT100M; evs.suspect_timeout=PT1S'; +connection node_3; Suspending node ... +connection node_1; SET SESSION wsrep_sync_wait = 0; SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 2 1 CREATE TABLE t1 (f1 INTEGER); INSERT INTO t1 VALUES (1); +connection node_2; SET SESSION wsrep_sync_wait = 0; SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 2 @@ -17,4 +22,5 @@ COUNT(*) = 1 1 DROP TABLE t1; Resuming node ... +connection node_3; CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)"); diff --git a/mysql-test/suite/galera_3nodes/r/galera_garbd.result b/mysql-test/suite/galera_3nodes/r/galera_garbd.result index 180aade029c..2d70b1742ab 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_garbd.result +++ b/mysql-test/suite/galera_3nodes/r/galera_garbd.result @@ -1,17 +1,25 @@ Killing node #3 to free ports for garbd ... +connection node_1; Starting garbd ... CREATE TABLE t1 (f1 INTEGER); INSERT INTO t1 VALUES (1); +connection node_2; SELECT COUNT(*) = 1 FROM t1; COUNT(*) = 1 1 Killing garbd ... +connection node_1; INSERT INTO t1 VALUES (2); +connection node_2; SELECT COUNT(*) = 2 FROM t1; COUNT(*) = 2 1 DROP TABLE t1; Restarting node #3 to satisfy MTR's end-of-test checks +connection node_3; +connection node_1; CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)"); +connection node_2; CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)"); +connection node_3; CALL mtr.add_suppression("WSREP: Protocol violation\. JOIN message sender 1\.0 \(.*\) is not in state transfer \(SYNCED\)"); diff --git a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result index 3d4dbcc00b0..aa3e349eda7 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result +++ b/mysql-test/suite/galera_3nodes/r/galera_ist_gcache_rollover.result @@ -1,6 +1,7 @@ connection node_1; connection node_2; connection node_3; +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); INSERT INTO t1 VALUES (01), (02), (03), (04), (05); connection node_2; diff --git a/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result b/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result index 69995acb982..3405beef12f 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result +++ b/mysql-test/suite/galera_3nodes/r/galera_pc_bootstrap.result @@ -1,8 +1,13 @@ CREATE TABLE t1 (f1 INTEGER); +connection node_1; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +connection node_2; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3; +connection node_3; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; SET SESSION wsrep_sync_wait = 0; +connection node_2; SET GLOBAL wsrep_provider_options = 'pc.bootstrap=1'; SHOW STATUS LIKE 'wsrep_cluster_size'; Variable_name Value @@ -11,15 +16,21 @@ SHOW STATUS LIKE 'wsrep_cluster_status'; Variable_name Value wsrep_cluster_status Primary INSERT INTO t1 VALUES (1); +connection node_2; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +connection node_1; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +connection node_3; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +connection node_1; SELECT COUNT(*) FROM t1; COUNT(*) 1 +connection node_2; SELECT COUNT(*) FROM t1; COUNT(*) 1 +connection node_3; SELECT COUNT(*) FROM t1; COUNT(*) 1 diff --git a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result index 9f845ffe776..240232d9c96 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result +++ b/mysql-test/suite/galera_3nodes/r/galera_pc_weight.result @@ -1,9 +1,11 @@ +connection node_1; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 3 SET GLOBAL wsrep_provider_options = 'pc.weight=3'; SELECT VARIABLE_VALUE = 5 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 5 SET GLOBAL wsrep_provider_options = 'gmcast.isolate=1'; +connection node_2; SET SESSION wsrep_sync_wait=0; SET SESSION wsrep_on=OFF; SET SESSION wsrep_on=ON; @@ -27,6 +29,7 @@ wsrep_local_state 0 SHOW STATUS LIKE 'wsrep_local_state_comment'; Variable_name Value wsrep_local_state_comment Initialized +connection node_3; SET SESSION wsrep_sync_wait=0; SET SESSION wsrep_on=OFF; SET SESSION wsrep_on=ON; @@ -50,6 +53,7 @@ wsrep_local_state 0 SHOW STATUS LIKE 'wsrep_local_state_comment'; Variable_name Value wsrep_local_state_comment Initialized +connection node_1; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 3 SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; @@ -70,7 +74,11 @@ VARIABLE_VALUE = 'Synced' SET GLOBAL wsrep_provider_options = 'pc.weight=1'; SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_weight'; VARIABLE_VALUE = 1 +connection node_1; SET GLOBAL wsrep_provider_options = 'gmcast.isolate=0'; +connection node_2; +connection node_3; +connection node_1; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 3 1 @@ -91,6 +99,7 @@ VARIABLE_VALUE = 4 SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; VARIABLE_VALUE = 'Synced' 1 +connection node_2; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 3 1 @@ -111,6 +120,7 @@ VARIABLE_VALUE = 4 SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; VARIABLE_VALUE = 'Synced' 1 +connection node_3; SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 3 1 @@ -131,12 +141,15 @@ VARIABLE_VALUE = 4 SELECT VARIABLE_VALUE = 'Synced' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_local_state_comment'; VARIABLE_VALUE = 'Synced' 1 +connection node_1; SET GLOBAL wsrep_provider_options = 'pc.weight=1'; CALL mtr.add_suppression('WSREP: gcs_caused\\(\\) returned -1'); +connection node_2; CALL mtr.add_suppression('overriding reported weight for'); CALL mtr.add_suppression('SYNC message from member'); CALL mtr.add_suppression('user message in state LEAVING'); CALL mtr.add_suppression('sending install message failed: (Transport endpoint is not connected|Socket is not connected)'); +connection node_3; CALL mtr.add_suppression('WSREP: user message in state LEAVING'); CALL mtr.add_suppression('sending install message failed: (Transport endpoint is not connected|Socket is not connected)'); CALL mtr.add_suppression('overriding reported weight for'); diff --git a/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result b/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result index 21f747d280b..45b4d63fb4f 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result +++ b/mysql-test/suite/galera_3nodes/r/galera_safe_to_bootstrap.result @@ -1,22 +1,49 @@ +connection node_1; +connection node_2; +connection node_3; +connection node_1; CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] +connection node_2; +connection node_1; include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] +connection node_3; +connection node_1; include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 1'] +connection node_2; +connection node_1; include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] include/assert_grep.inc [grastate.dat does not have 'safe_to_bootstrap: 0'] +connection node_2; +connection node_1; SET SESSION wsrep_on = OFF; Killing server ... safe_to_bootstrap: 1 safe_to_bootstrap: 0 safe_to_bootstrap: 0 +connection node_1; +connection node_2; +connection node_3; +connection node_2; +CALL mtr.add_suppression("WSREP: no nodes coming from prim view, prim not possible"); +CALL mtr.add_suppression("WSREP: It may not be safe to bootstrap the cluster from this node"); +CALL mtr.add_suppression("WSREP: wsrep::connect(.*) failed: 7"); +CALL mtr.add_suppression("Aborting"); +CALL mtr.add_suppression("WSREP: moving position backwards: [0-9]+ -> 0"); CALL mtr.add_suppression("Failed to prepare for incremental state transfer"); +connection node_3; +CALL mtr.add_suppression("WSREP: no nodes coming from prim view, prim not possible"); +CALL mtr.add_suppression("WSREP: It may not be safe to bootstrap the cluster from this node"); +CALL mtr.add_suppression("WSREP: wsrep::connect(.*) failed: 7"); +CALL mtr.add_suppression("Aborting"); +CALL mtr.add_suppression("WSREP: moving position backwards: [0-9]+ -> 0"); CALL mtr.add_suppression("Failed to prepare for incremental state transfer"); SHOW CREATE TABLE t1; Table Create Table diff --git a/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result b/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result index 88780a2c87f..c6756bce210 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result +++ b/mysql-test/suite/galera_3nodes/r/galera_var_dirty_reads2.result @@ -1,6 +1,9 @@ CREATE TABLE t1 (f1 INTEGER); INSERT INTO t1 VALUES (1); +connection node_2; SET GLOBAL wsrep_provider_options='gmcast.isolate=1'; +connection node_1; +connection node_2; SET SESSION wsrep_sync_wait = 0; SET SESSION wsrep_dirty_reads = 1; SELECT f1 FROM t1; @@ -45,4 +48,6 @@ SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.PROCESSLIST; COUNT(*) > 0 1 SET GLOBAL wsrep_provider_options='gmcast.isolate=0'; +connection node_1; +connection node_2; DROP TABLE t1; diff --git a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test index 03236a3cb93..4dab936c343 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test +++ b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test @@ -56,8 +56,8 @@ DROP TABLE t1; # Reconnect node #3 so that MTR's end-of-test checks can run ---connection node_3 --source include/galera_resume.inc +--connection node_3 --source include/wait_until_connected_again.inc CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)"); diff --git a/mysql-test/suite/galera_3nodes/t/galera_garbd.test b/mysql-test/suite/galera_3nodes/t/galera_garbd.test index a68ba8ce15b..5509c4628c9 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_garbd.test +++ b/mysql-test/suite/galera_3nodes/t/galera_garbd.test @@ -11,6 +11,8 @@ --let $galera_connection_name = node_3 --let $galera_server_number = 3 --source include/galera_connect.inc +--let $gp3 = `SELECT SUBSTR(@@wsrep_provider_options, LOCATE('base_port =', @@wsrep_provider_options) + LENGTH('base_port = '))` +--let $galera_port_3 = `SELECT SUBSTR('$gp3', 1, LOCATE(';', '$gp3') - 1)` --source include/shutdown_mysqld.inc --connection node_1 @@ -18,7 +20,9 @@ --source include/wait_condition.inc --echo Starting garbd ... ---exec `dirname $WSREP_PROVIDER`/garb/garbd --address "gcomm://127.0.0.1:$NODE_GALERAPORT_1" --group my_wsrep_cluster --options 'base_port=$NODE_GALERAPORT_3' > $MYSQL_TMP_DIR/garbd.log 2>&1 & +--let $gp1 = `SELECT SUBSTR(@@wsrep_provider_options, LOCATE('base_port =', @@wsrep_provider_options) + LENGTH('base_port = '))` +--let $galera_port_1 = `SELECT SUBSTR('$gp1', 1, LOCATE(';', '$gp1') - 1)` +--exec `dirname $WSREP_PROVIDER`/../../bin/garb/garbd --address "gcomm://127.0.0.1:$galera_port_1" --group my_wsrep_cluster --options 'base_port=$galera_port_3' > $MYSQL_TMP_DIR/garbd.log 2>&1 & --sleep 5 @@ -32,7 +36,7 @@ INSERT INTO t1 VALUES (1); SELECT COUNT(*) = 1 FROM t1; --echo Killing garbd ... ---exec pkill --oldest --full garbd.*$NODE_GALERAPORT_3 +--exec pkill --oldest --full garbd.*$galera_port_3 --sleep 5 diff --git a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf index 821175220ac..303087dffbb 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf +++ b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.cnf @@ -1,11 +1,11 @@ !include ../galera_3nodes.cnf [mysqld.1] -wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true;gcache.size=1M' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.ignore_sb=true;gcache.size=1M' [mysqld.2] -wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true;gcache.size=1M' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.ignore_sb=true;gcache.size=1M' [mysqld.3] -wsrep_provider_options='base_port=@mysqld.3.#galera_port;pc.ignore_sb=true;gcache.size=1M' +wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.3.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;pc.ignore_sb=true;gcache.size=1M' diff --git a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test index a67b30e3fa1..ebc756d60b1 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test +++ b/mysql-test/suite/galera_3nodes/t/galera_ist_gcache_rollover.test @@ -23,6 +23,7 @@ --let $node_3=node_3 --source ../galera/include/auto_increment_offset_save.inc +--connection node_1 CREATE TABLE t1 (f1 INTEGER PRIMARY KEY); INSERT INTO t1 VALUES (01), (02), (03), (04), (05); diff --git a/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test b/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test index 88d0cfba4f4..b7b6c66e5ad 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test +++ b/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test @@ -1,8 +1,19 @@ # # Test the safe_to_bootstrap in grastate.dat # - --source include/galera_cluster.inc + +--let $galera_connection_name = node_3 +--let $galera_server_number = 3 +--source include/galera_connect.inc + +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--let $node_3=node_3 +--source ../galera/include/auto_increment_offset_save.inc + +--connection node_1 CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; # @@ -47,8 +58,6 @@ CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; # # Shut down one more node # - ---connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3 --connection node_3 --source include/shutdown_mysqld.inc @@ -129,9 +138,9 @@ SET SESSION wsrep_on = OFF; # --error 1 ---exec $MYSQLD --defaults-group-suffix=.2 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-new-cluster | grep 'This node is not safe to bootstrap the cluster' +--exec $MYSQLD --defaults-group-suffix=.2 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-new-cluster --wsrep-cluster-address='gcomm://' | grep 'This node is not safe to bootstrap the cluster' --error 1 ---exec $MYSQLD --defaults-group-suffix=.3 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-new-cluster | grep 'This node is not safe to bootstrap the cluster' +--exec $MYSQLD --defaults-group-suffix=.3 --defaults-file=$MYSQLTEST_VARDIR/my.cnf --wsrep-new-cluster --wsrep-cluster-address='gcomm://' | grep 'This node is not safe to bootstrap the cluster' # # Attempt to bootstrap starting from node #1, should succeed @@ -154,10 +163,23 @@ SET SESSION wsrep_on = OFF; --source include/wait_condition.inc --connection node_2 +CALL mtr.add_suppression("WSREP: no nodes coming from prim view, prim not possible"); +CALL mtr.add_suppression("WSREP: It may not be safe to bootstrap the cluster from this node"); +CALL mtr.add_suppression("WSREP: wsrep::connect(.*) failed: 7"); +CALL mtr.add_suppression("Aborting"); +CALL mtr.add_suppression("WSREP: moving position backwards: [0-9]+ -> 0"); CALL mtr.add_suppression("Failed to prepare for incremental state transfer"); --connection node_3 +CALL mtr.add_suppression("WSREP: no nodes coming from prim view, prim not possible"); +CALL mtr.add_suppression("WSREP: It may not be safe to bootstrap the cluster from this node"); +CALL mtr.add_suppression("WSREP: wsrep::connect(.*) failed: 7"); +CALL mtr.add_suppression("Aborting"); +CALL mtr.add_suppression("WSREP: moving position backwards: [0-9]+ -> 0"); CALL mtr.add_suppression("Failed to prepare for incremental state transfer"); SHOW CREATE TABLE t1; DROP TABLE t1; + +# Restore original auto_increment_offset values. +--source ../galera/include/auto_increment_offset_restore.inc From 6caf9ec425a12ed54741cdf4c4a238c45cabd898 Mon Sep 17 00:00:00 2001 From: Kentoku Date: Tue, 20 Nov 2018 00:12:58 +0900 Subject: [PATCH 09/91] Update Spider to version 3.3.14. Add direct left outer join/right outer join/inner join feature --- storage/spider/ha_spider.cc | 191 +++- storage/spider/ha_spider.h | 94 +- storage/spider/hs_client/hs_compat.h | 2 +- .../include/direct_join_using_deinit.inc | 9 + .../spider/include/direct_join_using_init.inc | 13 + .../include/direct_left_join_deinit.inc | 9 + .../spider/include/direct_left_join_init.inc | 13 + .../direct_left_join_nullable_deinit.inc | 9 + .../direct_left_join_nullable_init.inc | 13 + ...direct_left_right_join_nullable_deinit.inc | 9 + .../direct_left_right_join_nullable_init.inc | 13 + ...t_left_right_left_join_nullable_deinit.inc | 9 + ...ect_left_right_left_join_nullable_init.inc | 13 + .../include/direct_right_join_deinit.inc | 9 + .../spider/include/direct_right_join_init.inc | 13 + .../direct_right_join_nullable_deinit.inc | 9 + .../direct_right_join_nullable_init.inc | 13 + ...direct_right_left_join_nullable_deinit.inc | 9 + .../direct_right_left_join_nullable_init.inc | 13 + ..._right_left_right_join_nullable_deinit.inc | 9 + ...ct_right_left_right_join_nullable_init.inc | 13 + .../mysql-test/spider/include/init_spider.inc | 42 +- .../spider/r/direct_join_using.result | 108 +++ .../spider/r/direct_left_join.result | 108 +++ .../spider/r/direct_left_join_nullable.result | 113 +++ .../r/direct_left_right_join_nullable.result | 113 +++ ...irect_left_right_left_join_nullable.result | 112 +++ .../spider/r/direct_right_join.result | 108 +++ .../r/direct_right_join_nullable.result | 113 +++ .../r/direct_right_left_join_nullable.result | 112 +++ ...rect_right_left_right_join_nullable.result | 113 +++ .../spider/r/show_system_tables.result | 37 + .../spider/t/direct_join_using.test | 197 ++++ .../mysql-test/spider/t/direct_left_join.test | 197 ++++ .../spider/t/direct_left_join_nullable.test | 212 ++++ .../t/direct_left_right_join_nullable.test | 212 ++++ .../direct_left_right_left_join_nullable.test | 212 ++++ .../spider/t/direct_right_join.test | 197 ++++ .../spider/t/direct_right_join_nullable.test | 212 ++++ .../t/direct_right_left_join_nullable.test | 212 ++++ ...direct_right_left_right_join_nullable.test | 212 ++++ .../spider/t/show_system_tables.test | 26 + storage/spider/scripts/install_spider.sql | 88 +- storage/spider/spd_conn.cc | 9 +- storage/spider/spd_conn.h | 4 +- storage/spider/spd_copy_tables.cc | 45 +- storage/spider/spd_db_conn.cc | 417 +++++--- storage/spider/spd_db_conn.h | 23 +- storage/spider/spd_db_handlersocket.cc | 105 +- storage/spider/spd_db_handlersocket.h | 7 +- storage/spider/spd_db_include.h | 10 +- storage/spider/spd_db_mysql.cc | 904 ++++++++++++++---- storage/spider/spd_db_mysql.h | 45 +- storage/spider/spd_db_oracle.cc | 288 ++++-- storage/spider/spd_db_oracle.h | 9 +- storage/spider/spd_direct_sql.cc | 79 +- storage/spider/spd_environ.h | 15 +- storage/spider/spd_group_by_handler.cc | 63 +- storage/spider/spd_i_s.cc | 4 +- storage/spider/spd_include.h | 85 +- storage/spider/spd_param.cc | 27 +- storage/spider/spd_param.h | 5 +- storage/spider/spd_ping_table.cc | 2 +- storage/spider/spd_sys_table.cc | 163 +++- storage/spider/spd_sys_table.h | 33 +- storage/spider/spd_table.cc | 42 +- storage/spider/spd_trx.cc | 14 +- 67 files changed, 5242 insertions(+), 697 deletions(-) create mode 100644 storage/spider/mysql-test/spider/include/direct_join_using_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_join_using_init.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_left_join_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_left_join_init.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_left_join_nullable_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_left_join_nullable_init.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_left_right_join_nullable_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_left_right_join_nullable_init.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_left_right_left_join_nullable_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_left_right_left_join_nullable_init.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_right_join_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_right_join_init.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_right_join_nullable_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_right_join_nullable_init.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_right_left_join_nullable_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_right_left_join_nullable_init.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_right_left_right_join_nullable_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/direct_right_left_right_join_nullable_init.inc create mode 100644 storage/spider/mysql-test/spider/r/direct_join_using.result create mode 100644 storage/spider/mysql-test/spider/r/direct_left_join.result create mode 100644 storage/spider/mysql-test/spider/r/direct_left_join_nullable.result create mode 100644 storage/spider/mysql-test/spider/r/direct_left_right_join_nullable.result create mode 100644 storage/spider/mysql-test/spider/r/direct_left_right_left_join_nullable.result create mode 100644 storage/spider/mysql-test/spider/r/direct_right_join.result create mode 100644 storage/spider/mysql-test/spider/r/direct_right_join_nullable.result create mode 100644 storage/spider/mysql-test/spider/r/direct_right_left_join_nullable.result create mode 100644 storage/spider/mysql-test/spider/r/direct_right_left_right_join_nullable.result create mode 100644 storage/spider/mysql-test/spider/r/show_system_tables.result create mode 100644 storage/spider/mysql-test/spider/t/direct_join_using.test create mode 100644 storage/spider/mysql-test/spider/t/direct_left_join.test create mode 100644 storage/spider/mysql-test/spider/t/direct_left_join_nullable.test create mode 100644 storage/spider/mysql-test/spider/t/direct_left_right_join_nullable.test create mode 100644 storage/spider/mysql-test/spider/t/direct_left_right_left_join_nullable.test create mode 100644 storage/spider/mysql-test/spider/t/direct_right_join.test create mode 100644 storage/spider/mysql-test/spider/t/direct_right_join_nullable.test create mode 100644 storage/spider/mysql-test/spider/t/direct_right_left_join_nullable.test create mode 100644 storage/spider/mysql-test/spider/t/direct_right_left_right_join_nullable.test create mode 100644 storage/spider/mysql-test/spider/t/show_system_tables.test diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index bd302f155d2..8471af40289 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -64,6 +64,9 @@ extern HASH spider_open_tables; #endif extern pthread_mutex_t spider_lgtm_tblhnd_share_mutex; +/* UTC time zone for timestamp columns */ +extern Time_zone *UTC; + ha_spider::ha_spider( ) : handler(spider_hton_ptr, NULL) { @@ -7963,7 +7966,7 @@ int ha_spider::cmp_ref( if ((ret = (*field)->cmp_binary_offset((uint) ptr_diff))) { DBUG_PRINT("info",("spider different at %s", - (*field)->field_name.str)); + SPIDER_field_name_str(*field))); break; } } @@ -9959,21 +9962,38 @@ int ha_spider::end_bulk_update( DBUG_RETURN(0); } +#ifdef SPIDER_UPDATE_ROW_HAS_CONST_NEW_DATA int ha_spider::bulk_update_row( const uchar *old_data, const uchar *new_data, ha_rows *dup_key_found -) { +) +#else +int ha_spider::bulk_update_row( + const uchar *old_data, + uchar *new_data, + ha_rows *dup_key_found +) +#endif +{ DBUG_ENTER("ha_spider::bulk_update_row"); DBUG_PRINT("info",("spider this=%p", this)); *dup_key_found = 0; DBUG_RETURN(update_row(old_data, new_data)); } +#ifdef SPIDER_UPDATE_ROW_HAS_CONST_NEW_DATA int ha_spider::update_row( const uchar *old_data, const uchar *new_data -) { +) +#else +int ha_spider::update_row( + const uchar *old_data, + uchar *new_data +) +#endif +{ int error_num; THD *thd = ha_thd(); backup_error_status(); @@ -10064,10 +10084,24 @@ int ha_spider::update_row( #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS -int ha_spider::direct_update_rows_init(List *update_fields, uint mode, - KEY_MULTI_RANGE *ranges, - uint range_count, bool sorted, - const uchar *new_data) +#ifdef SPIDER_MDEV_16246 +int ha_spider::direct_update_rows_init( + List *update_fields, + uint mode, + KEY_MULTI_RANGE *ranges, + uint range_count, + bool sorted, + uchar *new_data +) +#else +int ha_spider::direct_update_rows_init( + uint mode, + KEY_MULTI_RANGE *ranges, + uint range_count, + bool sorted, + uchar *new_data +) +#endif { #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) int error_num; @@ -10095,8 +10129,13 @@ int ha_spider::direct_update_rows_init(List *update_fields, uint mode, pre_direct_init_result)); DBUG_RETURN(pre_direct_init_result); } +#ifdef SPIDER_MDEV_16246 DBUG_RETURN(bulk_access_link_exec_tgt->spider->direct_update_rows_init( update_fields, mode, ranges, range_count, sorted, new_data)); +#else + DBUG_RETURN(bulk_access_link_exec_tgt->spider->direct_update_rows_init( + mode, ranges, range_count, sorted, new_data)); +#endif } #endif direct_update_init( @@ -10200,6 +10239,7 @@ int ha_spider::direct_update_rows_init(List *update_fields, uint mode, DBUG_RETURN(HA_ERR_WRONG_COMMAND); } #else +#ifdef SPIDER_MDEV_16246 /** Perform initialization for a direct update request. @@ -10209,37 +10249,43 @@ int ha_spider::direct_update_rows_init(List *update_fields, uint mode, 0 Success. */ -int ha_spider::direct_update_rows_init(List *update_fields) +int ha_spider::direct_update_rows_init( + List *update_fields +) +#else +int ha_spider::direct_update_rows_init() +#endif { st_select_lex *select_lex; longlong select_limit; longlong offset_limit; - List_iterator it(*update_fields); + List_iterator it(*direct_update_fields); Item *item; Field *field; THD *thd = trx->thd; DBUG_ENTER("ha_spider::direct_update_rows_init"); DBUG_PRINT("info",("spider this=%p", this)); - - while ((item = it++)) + if (thd->variables.time_zone != UTC) { - if (item->type() == Item::FIELD_ITEM) + while ((item = it++)) { - field = ((Item_field *)item)->field; - - if (field->type() == FIELD_TYPE_TIMESTAMP && - field->flags & UNIQUE_KEY_FLAG) + if (item->type() == Item::FIELD_ITEM) { - /* - Spider cannot perform direct update on unique timestamp fields. - To avoid false duplicate key errors, the table needs to be - updated one row at a time. - */ - DBUG_RETURN(HA_ERR_WRONG_COMMAND); + field = ((Item_field *)item)->field; + + if (field->type() == FIELD_TYPE_TIMESTAMP && + field->flags & UNIQUE_KEY_FLAG) + { + /* + Spider cannot perform direct update on unique timestamp fields. + To avoid false duplicate key errors, the table needs to be + updated one row at a time. + */ + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + } } } } - #ifdef HA_CAN_BULK_ACCESS if ( bulk_access_executing && @@ -10257,8 +10303,12 @@ int ha_spider::direct_update_rows_init(List *update_fields) pre_direct_init_result)); DBUG_RETURN(pre_direct_init_result); } +#ifdef SPIDER_MDEV_16246 DBUG_RETURN(bulk_access_link_exec_tgt->spider-> - direct_update_rows_init(List *update_fields)); + direct_update_rows_init(update_fields)); +#else + DBUG_RETURN(bulk_access_link_exec_tgt->spider->direct_update_rows_init()); +#endif } #endif direct_update_init( @@ -10329,30 +10379,54 @@ int ha_spider::direct_update_rows_init(List *update_fields) #ifdef HA_CAN_BULK_ACCESS #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS -int ha_spider::pre_direct_update_rows_init(List *update_fields, - uint mode, - KEY_MULTI_RANGE *ranges, - uint range_count, bool sorted, - const uchar *new_data) +#ifdef SPIDER_MDEV_16246 +int ha_spider::pre_direct_update_rows_init( + List *update_fields, + uint mode, + KEY_MULTI_RANGE *ranges, + uint range_count, + bool sorted, + uchar *new_data +) +#else +int ha_spider::pre_direct_update_rows_init( + uint mode, + KEY_MULTI_RANGE *ranges, + uint range_count, + bool sorted, + uchar *new_data +) +#endif { int error_num; DBUG_ENTER("ha_spider::pre_direct_update_rows_init"); DBUG_PRINT("info",("spider this=%p", this)); if (bulk_access_started) { +#ifdef SPIDER_MDEV_16246 error_num = bulk_access_link_current->spider-> - pre_direct_update_rows_init(update_fields, mode, ranges, range_count, - sorted, new_data); + pre_direct_update_rows_init( + update_fields, mode, ranges, range_count, sorted, new_data); +#else + error_num = bulk_access_link_current->spider-> + pre_direct_update_rows_init( + mode, ranges, range_count, sorted, new_data); +#endif bulk_access_link_current->spider->bulk_access_pre_called = TRUE; bulk_access_link_current->called = TRUE; DBUG_RETURN(error_num); } - pre_direct_init_result = direct_update_rows_init(update_fields, mode, - ranges, range_count, - sorted, new_data); +#ifdef SPIDER_MDEV_16246 + pre_direct_init_result = direct_update_rows_init( + update_fields, mode, ranges, range_count, sorted, new_data); +#else + pre_direct_init_result = direct_update_rows_init( + mode, ranges, range_count, sorted, new_data); +#endif DBUG_RETURN(pre_direct_init_result); } #else +#ifdef SPIDER_MDEV_16246 /** Do initialization for performing parallel direct update for a handlersocket update request. @@ -10363,20 +10437,34 @@ int ha_spider::pre_direct_update_rows_init(List *update_fields, 0 Success. */ -int ha_spider::pre_direct_update_rows_init(List *update_fields) +int ha_spider::pre_direct_update_rows_init( + List *update_fields +) +#else +int ha_spider::pre_direct_update_rows_init() +#endif { int error_num; DBUG_ENTER("ha_spider::pre_direct_update_rows_init"); DBUG_PRINT("info",("spider this=%p", this)); if (bulk_access_started) { +#ifdef SPIDER_MDEV_16246 error_num = bulk_access_link_current->spider-> - pre_direct_update_rows_init(update_fields); + pre_direct_update_rows_init(update_fields); +#else + error_num = bulk_access_link_current->spider-> + pre_direct_update_rows_init(); +#endif bulk_access_link_current->spider->bulk_access_pre_called = TRUE; bulk_access_link_current->called = TRUE; DBUG_RETURN(error_num); } +#ifdef SPIDER_MDEV_16246 pre_direct_init_result = direct_update_rows_init(update_fields); +#else + pre_direct_init_result = direct_update_rows_init(); +#endif DBUG_RETURN(pre_direct_init_result); } #endif @@ -11305,7 +11393,7 @@ int ha_spider::create( DBUG_PRINT("info", ("spider alter_info.flags: %llu alter_info.partition_flags: %lu", - thd->lex->alter_info.flags, thd->lex->alter_info.partition_flags)); + thd->lex->alter_info.flags, thd->lex->alter_info.partition_flags)); if ((thd->lex->alter_info.partition_flags & ( SPIDER_ALTER_PARTITION_ADD | SPIDER_ALTER_PARTITION_DROP | @@ -11501,7 +11589,7 @@ int ha_spider::rename_table( DBUG_PRINT("info", ("spider alter_info.flags: %llu alter_info.partition_flags: %lu", - thd->lex->alter_info.flags, thd->lex->alter_info.partition_flags)); + thd->lex->alter_info.flags, thd->lex->alter_info.partition_flags)); if ( (thd->lex->alter_info.partition_flags & ( @@ -11697,7 +11785,7 @@ int ha_spider::delete_table( DBUG_PRINT("info", ("spider alter_info.flags: %llu alter_info.partition_flags: %lu", - thd->lex->alter_info.flags, thd->lex->alter_info.partition_flags)); + thd->lex->alter_info.flags, thd->lex->alter_info.partition_flags)); if ( sql_command == SQLCOM_ALTER_TABLE && (thd->lex->alter_info.partition_flags & @@ -13514,6 +13602,7 @@ void ha_spider::check_pre_call( bool use_parallel ) { THD* thd = ha_thd(); + LEX *lex = thd->lex; st_select_lex *select_lex = spider_get_select_lex(this); int skip_parallel_search = spider_param_skip_parallel_search(thd, share->skip_parallel_search); @@ -13522,11 +13611,15 @@ void ha_spider::check_pre_call( if ( ( (skip_parallel_search & 1) && - thd->lex && thd->lex->sql_command != SQLCOM_SELECT // such like insert .. select .. + lex->sql_command != SQLCOM_SELECT // such like insert .. select .. ) || ( (skip_parallel_search & 2) && +#ifdef SPIDER_SQL_CACHE_IS_IN_LEX + lex->sql_cache == LEX::SQL_NO_CACHE // for mysqldump +#else select_lex && select_lex->sql_cache == SELECT_LEX::SQL_NO_CACHE // for mysqldump +#endif ) ) { use_pre_call = FALSE; @@ -15672,12 +15765,23 @@ int ha_spider::mk_bulk_tmp_table_and_bulk_start() dbton_hdl->first_link_idx >= 0 && dbton_hdl->need_copy_for_update(roop_count) ) { +#ifdef SPIDER_use_LEX_CSTRING_for_Field_blob_constructor + LEX_CSTRING field_name = {STRING_WITH_LEN("a")}; + if ( + !tmp_table[roop_count] && + !(tmp_table[roop_count] = spider_mk_sys_tmp_table( + trx->thd, table, &result_list.upd_tmp_tbl_prms[roop_count], + &field_name, result_list.update_sqls[roop_count].charset())) + ) +#else if ( !tmp_table[roop_count] && !(tmp_table[roop_count] = spider_mk_sys_tmp_table( trx->thd, table, &result_list.upd_tmp_tbl_prms[roop_count], "a", result_list.update_sqls[roop_count].charset())) - ) { + ) +#endif + { error_num = HA_ERR_OUT_OF_MEM; goto error_2; } @@ -15775,8 +15879,7 @@ int ha_spider::print_item_type( if ( dbton_hdl->first_link_idx >= 0 && (error_num = spider_db_print_item_type(item, NULL, this, str, - alias, alias_length, dbton_id, - FALSE, NULL)) + alias, alias_length, dbton_id, FALSE, NULL)) ) { DBUG_RETURN(error_num); } diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h index 66e5cf8a452..d33d9a3a7dc 100644 --- a/storage/spider/ha_spider.h +++ b/storage/spider/ha_spider.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -576,6 +576,7 @@ public: ha_rows *dup_key_found ); int end_bulk_update(); +#ifdef SPIDER_UPDATE_ROW_HAS_CONST_NEW_DATA int bulk_update_row( const uchar *old_data, const uchar *new_data, @@ -585,31 +586,92 @@ public: const uchar *old_data, const uchar *new_data ); +#else + int bulk_update_row( + const uchar *old_data, + uchar *new_data, + ha_rows *dup_key_found + ); + int update_row( + const uchar *old_data, + uchar *new_data + ); +#endif #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS - inline int direct_update_rows_init(List *update_fields) - { +#ifdef SPIDER_MDEV_16246 + inline int direct_update_rows_init( + List *update_fields + ) { return direct_update_rows_init(update_fields, 2, NULL, 0, FALSE, NULL); } - int direct_update_rows_init(List *update_fields, uint mode, - KEY_MULTI_RANGE *ranges, uint range_count, - bool sorted, const uchar *new_data); + int direct_update_rows_init( + List *update_fields, + uint mode, + KEY_MULTI_RANGE *ranges, + uint range_count, + bool sorted, + uchar *new_data + ); #else - int direct_update_rows_init(List *update_fields); + inline int direct_update_rows_init() + { + return direct_update_rows_init(2, NULL, 0, FALSE, NULL); + } + int direct_update_rows_init( + uint mode, + KEY_MULTI_RANGE *ranges, + uint range_count, + bool sorted, + uchar *new_data + ); +#endif +#else +#ifdef SPIDER_MDEV_16246 + int direct_update_rows_init( + List *update_fields + ); +#else + int direct_update_rows_init(); +#endif #endif #ifdef HA_CAN_BULK_ACCESS #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS - inline int pre_direct_update_rows_init(List *update_fields) - { - return pre_direct_update_rows_init(update_fields, - 2, NULL, 0, FALSE, NULL); +#ifdef SPIDER_MDEV_16246 + inline int pre_direct_update_rows_init( + List *update_fields + ) { + return pre_direct_update_rows_init(update_fields, 2, NULL, 0, FALSE, NULL); } - int pre_direct_update_rows_init(List *update_fields, - uint mode, KEY_MULTI_RANGE *ranges, - uint range_count, bool sorted, - uchar *new_data); + int pre_direct_update_rows_init( + List *update_fields, + uint mode, + KEY_MULTI_RANGE *ranges, + uint range_count, + bool sorted, + uchar *new_data + ); #else - int pre_direct_update_rows_init(List *update_fields); + inline int pre_direct_update_rows_init() + { + return pre_direct_update_rows_init(2, NULL, 0, FALSE, NULL); + } + int pre_direct_update_rows_init( + uint mode, + KEY_MULTI_RANGE *ranges, + uint range_count, + bool sorted, + uchar *new_data + ); +#endif +#else +#ifdef SPIDER_MDEV_16246 + int pre_direct_update_rows_init( + List *update_fields + ); +#else + int pre_direct_update_rows_init(); +#endif #endif #endif #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS diff --git a/storage/spider/hs_client/hs_compat.h b/storage/spider/hs_client/hs_compat.h index e832b2974da..a1b18fe1b38 100644 --- a/storage/spider/hs_client/hs_compat.h +++ b/storage/spider/hs_client/hs_compat.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 Kentoku Shiba +/* Copyright (C) 2013-2018 Kentoku Shiba 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 diff --git a/storage/spider/mysql-test/spider/include/direct_join_using_deinit.inc b/storage/spider/mysql-test/spider/include/direct_join_using_deinit.inc new file mode 100644 index 00000000000..53bc29a0016 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_join_using_deinit.inc @@ -0,0 +1,9 @@ +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/direct_join_using_init.inc b/storage/spider/mysql-test/spider/include/direct_join_using_init.inc new file mode 100644 index 00000000000..7e4947bf078 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_join_using_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 diff --git a/storage/spider/mysql-test/spider/include/direct_left_join_deinit.inc b/storage/spider/mysql-test/spider/include/direct_left_join_deinit.inc new file mode 100644 index 00000000000..53bc29a0016 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_left_join_deinit.inc @@ -0,0 +1,9 @@ +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/direct_left_join_init.inc b/storage/spider/mysql-test/spider/include/direct_left_join_init.inc new file mode 100644 index 00000000000..7e4947bf078 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_left_join_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 diff --git a/storage/spider/mysql-test/spider/include/direct_left_join_nullable_deinit.inc b/storage/spider/mysql-test/spider/include/direct_left_join_nullable_deinit.inc new file mode 100644 index 00000000000..53bc29a0016 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_left_join_nullable_deinit.inc @@ -0,0 +1,9 @@ +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/direct_left_join_nullable_init.inc b/storage/spider/mysql-test/spider/include/direct_left_join_nullable_init.inc new file mode 100644 index 00000000000..7e4947bf078 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_left_join_nullable_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 diff --git a/storage/spider/mysql-test/spider/include/direct_left_right_join_nullable_deinit.inc b/storage/spider/mysql-test/spider/include/direct_left_right_join_nullable_deinit.inc new file mode 100644 index 00000000000..53bc29a0016 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_left_right_join_nullable_deinit.inc @@ -0,0 +1,9 @@ +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/direct_left_right_join_nullable_init.inc b/storage/spider/mysql-test/spider/include/direct_left_right_join_nullable_init.inc new file mode 100644 index 00000000000..7e4947bf078 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_left_right_join_nullable_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 diff --git a/storage/spider/mysql-test/spider/include/direct_left_right_left_join_nullable_deinit.inc b/storage/spider/mysql-test/spider/include/direct_left_right_left_join_nullable_deinit.inc new file mode 100644 index 00000000000..53bc29a0016 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_left_right_left_join_nullable_deinit.inc @@ -0,0 +1,9 @@ +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/direct_left_right_left_join_nullable_init.inc b/storage/spider/mysql-test/spider/include/direct_left_right_left_join_nullable_init.inc new file mode 100644 index 00000000000..7e4947bf078 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_left_right_left_join_nullable_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 diff --git a/storage/spider/mysql-test/spider/include/direct_right_join_deinit.inc b/storage/spider/mysql-test/spider/include/direct_right_join_deinit.inc new file mode 100644 index 00000000000..53bc29a0016 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_right_join_deinit.inc @@ -0,0 +1,9 @@ +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/direct_right_join_init.inc b/storage/spider/mysql-test/spider/include/direct_right_join_init.inc new file mode 100644 index 00000000000..7e4947bf078 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_right_join_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 diff --git a/storage/spider/mysql-test/spider/include/direct_right_join_nullable_deinit.inc b/storage/spider/mysql-test/spider/include/direct_right_join_nullable_deinit.inc new file mode 100644 index 00000000000..53bc29a0016 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_right_join_nullable_deinit.inc @@ -0,0 +1,9 @@ +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/direct_right_join_nullable_init.inc b/storage/spider/mysql-test/spider/include/direct_right_join_nullable_init.inc new file mode 100644 index 00000000000..7e4947bf078 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_right_join_nullable_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 diff --git a/storage/spider/mysql-test/spider/include/direct_right_left_join_nullable_deinit.inc b/storage/spider/mysql-test/spider/include/direct_right_left_join_nullable_deinit.inc new file mode 100644 index 00000000000..53bc29a0016 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_right_left_join_nullable_deinit.inc @@ -0,0 +1,9 @@ +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/direct_right_left_join_nullable_init.inc b/storage/spider/mysql-test/spider/include/direct_right_left_join_nullable_init.inc new file mode 100644 index 00000000000..7e4947bf078 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_right_left_join_nullable_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 diff --git a/storage/spider/mysql-test/spider/include/direct_right_left_right_join_nullable_deinit.inc b/storage/spider/mysql-test/spider/include/direct_right_left_right_join_nullable_deinit.inc new file mode 100644 index 00000000000..53bc29a0016 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_right_left_right_join_nullable_deinit.inc @@ -0,0 +1,9 @@ +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/direct_right_left_right_join_nullable_init.inc b/storage/spider/mysql-test/spider/include/direct_right_left_right_join_nullable_init.inc new file mode 100644 index 00000000000..7e4947bf078 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/direct_right_left_right_join_nullable_init.inc @@ -0,0 +1,13 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 diff --git a/storage/spider/mysql-test/spider/include/init_spider.inc b/storage/spider/mysql-test/spider/include/init_spider.inc index c4d171d418e..1da1ec970b5 100644 --- a/storage/spider/mysql-test/spider/include/init_spider.inc +++ b/storage/spider/mysql-test/spider/include/init_spider.inc @@ -103,10 +103,17 @@ if (!$VERSION_COMPILE_OS_WIN) ); } +let $SERVER_NAME= + `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(version(), '-', 2), '-', -1)`; +let $SERVER_MAJOR_VERSION= + `SELECT SUBSTRING_INDEX(version(), '.', 1)`; +let $SERVER_MINOR_VERSION= + `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(version(), '.', 2), '.', -1)`; let $PLUGIN_VERSION= `SELECT SUBSTRING_INDEX(plugin_version, '.', 1) FROM information_schema.plugins WHERE plugin_name = 'SPIDER'`; + if (`SELECT IF($PLUGIN_VERSION = 1, 1, 0)`) { DROP TABLE IF EXISTS mysql.spider_xa; @@ -245,7 +252,16 @@ if (`SELECT IF($PLUGIN_VERSION = 2, 1, 0)`) } if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) { + let $ENGINE_NAME= + `SELECT IF (STRCMP('$SERVER_NAME', 'MariaDB') = 0, + IF ($SERVER_MAJOR_VERSION = 10, + IF ($SERVER_MINOR_VERSION < 4, 'MyISAM', + 'Aria transactional=1'), + IF ($SERVER_MAJOR_VERSION < 10, 'MyISAM', + 'Aria transactional=1')), + 'MyISAM')`; DROP TABLE IF EXISTS mysql.spider_xa; + eval CREATE TABLE mysql.spider_xa( format_id int not null default 0, gtrid_length int not null default 0, @@ -254,8 +270,9 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) status char(8) not null default '', PRIMARY KEY (data, format_id, gtrid_length), KEY idx1 (status) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_xa_member; + eval CREATE TABLE mysql.spider_xa_member( format_id int not null default 0, gtrid_length int not null default 0, @@ -276,8 +293,9 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) default_file text default null, default_group char(64) default null, KEY idx1 (data, format_id, gtrid_length, host) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_xa_failed_log; + eval CREATE TABLE mysql.spider_xa_failed_log( format_id int not null default 0, gtrid_length int not null default 0, @@ -301,8 +319,9 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) status char(8) not null default '', failed_time timestamp not null default current_timestamp, key idx1 (data, format_id, gtrid_length, host) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_tables; + eval CREATE TABLE mysql.spider_tables( db_name char(64) not null default '', table_name char(199) not null default '', @@ -332,8 +351,9 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) PRIMARY KEY (db_name, table_name, link_id), KEY idx1 (priority), UNIQUE KEY uidx1 (db_name, table_name, static_link_id) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_link_mon_servers; + eval CREATE TABLE mysql.spider_link_mon_servers( db_name char(64) not null default '', table_name char(199) not null default '', @@ -355,15 +375,17 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) default_file text default null, default_group char(64) default null, PRIMARY KEY (db_name, table_name, link_id, sid) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_link_failed_log; + eval CREATE TABLE mysql.spider_link_failed_log( db_name char(64) not null default '', table_name char(199) not null default '', link_id char(64) not null default '', failed_time timestamp not null default current_timestamp - ) ENGINE=MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_table_position_for_recovery; + eval CREATE TABLE mysql.spider_table_position_for_recovery( db_name char(64) not null default '', table_name char(199) not null default '', @@ -373,8 +395,9 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) position text, gtid text, primary key (db_name, table_name, failed_link_id, source_link_id) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_table_sts; + eval CREATE TABLE mysql.spider_table_sts( db_name char(64) not null default '', table_name char(199) not null default '', @@ -387,15 +410,16 @@ if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`) create_time datetime not null default '0000-00-00 00:00:00', update_time datetime not null default '0000-00-00 00:00:00', primary key (db_name, table_name) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; DROP TABLE IF EXISTS mysql.spider_table_crd; + eval CREATE TABLE mysql.spider_table_crd( db_name char(64) not null default '', table_name char(199) not null default '', key_seq int unsigned not null default 0, cardinality bigint not null default 0, primary key (db_name, table_name, key_seq) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin; } SET spider_internal_sql_log_off= 0; diff --git a/storage/spider/mysql-test/spider/r/direct_join_using.result b/storage/spider/mysql-test/spider/r/direct_join_using.result new file mode 100644 index 00000000000..66ae1503f9f --- /dev/null +++ b/storage/spider/mysql-test/spider/r/direct_join_using.result @@ -0,0 +1,108 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +test select 1 +connection master_1; +SELECT 1; +1 +1 +connection child2_1; +SELECT 1; +1 +1 + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_DROP_TABLES6 +CHILD2_1_DROP_TABLES5 +CHILD2_1_CREATE_TABLES +CHILD2_1_CREATE_TABLES6 +CHILD2_1_CREATE_TABLES5 +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +PRIMARY KEY(a), +KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1 +CREATE TABLE tbl_c ( +a INT AUTO_INCREMENT, +b INT DEFAULT 10, +c INT DEFAULT 11, +PRIMARY KEY(a), +KEY idx1(b), +KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT4_2_1 +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_c values (1,10,100),(2,20,200),(3,30,300),(4,40,400),(5,50,500); + +select test +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.a, c.b, c.c FROM tbl_a a join tbl_b b using(a) join tbl_c c using(a) ORDER BY a.b DESC; +a b c +5 50 500 +4 40 400 +3 30 300 +2 20 200 +1 10 100 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`b` `b`,t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r` t0,`auto_test_remote`.`ta_r_3` t1,`auto_test_remote`.`ta_r_int` t2 where ((t0.`a` = t1.`a`) and (t2.`a` = t1.`a`)) order by t0.`b` desc +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; +a b date_format(c, '%Y-%m-%d %H:%i:%s') +1 a 2000-01-01 00:00:00 +2 b 2000-01-02 00:00:00 +3 c 2000-01-03 00:00:00 +4 d 2000-01-04 00:00:00 +5 e 2000-01-05 00:00:00 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/direct_left_join.result b/storage/spider/mysql-test/spider/r/direct_left_join.result new file mode 100644 index 00000000000..b63f0661b2e --- /dev/null +++ b/storage/spider/mysql-test/spider/r/direct_left_join.result @@ -0,0 +1,108 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +test select 1 +connection master_1; +SELECT 1; +1 +1 +connection child2_1; +SELECT 1; +1 +1 + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_DROP_TABLES6 +CHILD2_1_DROP_TABLES5 +CHILD2_1_CREATE_TABLES +CHILD2_1_CREATE_TABLES6 +CHILD2_1_CREATE_TABLES5 +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +PRIMARY KEY(a), +KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1 +CREATE TABLE tbl_c ( +a INT AUTO_INCREMENT, +b INT DEFAULT 10, +c INT DEFAULT 11, +PRIMARY KEY(a), +KEY idx1(b), +KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT4_2_1 +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_c values (1,10,100),(2,20,200),(3,30,300),(4,40,400),(5,50,500); + +select test +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.a, c.b, c.c FROM tbl_a a left join tbl_b b on a.a = b.a left join tbl_c c on a.a = c.a ORDER BY a.b DESC; +a b c +5 50 500 +4 40 400 +3 30 300 +2 20 200 +1 10 100 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`b` `b`,t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r` t0 left join `auto_test_remote`.`ta_r_3` t1 on (t1.`a` = t0.`a`) left join `auto_test_remote`.`ta_r_int` t2 on (t2.`a` = t0.`a`) where 1 order by t0.`b` desc +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; +a b date_format(c, '%Y-%m-%d %H:%i:%s') +1 a 2000-01-01 00:00:00 +2 b 2000-01-02 00:00:00 +3 c 2000-01-03 00:00:00 +4 d 2000-01-04 00:00:00 +5 e 2000-01-05 00:00:00 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/direct_left_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_left_join_nullable.result new file mode 100644 index 00000000000..e646bc9bf38 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/direct_left_join_nullable.result @@ -0,0 +1,113 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +test select 1 +connection master_1; +SELECT 1; +1 +1 +connection child2_1; +SELECT 1; +1 +1 + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_DROP_TABLES6 +CHILD2_1_DROP_TABLES4 +CHILD2_1_DROP_TABLES3 +CHILD2_1_CREATE_TABLES +CHILD2_1_CREATE_TABLES6 +CHILD2_1_CREATE_TABLES4 +CHILD2_1_CREATE_TABLES3 +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1 +CREATE TABLE tbl_c ( +a INT AUTO_INCREMENT, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b), +KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1 +CREATE TABLE tbl_d ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1 +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +select test +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.a, c.b, c.c, d.a FROM tbl_d a left join tbl_c b on a.a = b.a left join tbl_b c on b.c = c.c left join tbl_a d on c.b = d.b ORDER BY a.a DESC; +a b c a +5 NULL NULL NULL +4 NULL NULL NULL +3 c 2000-01-03 00:00:00 NULL +2 b 2000-01-02 00:00:00 2 +1 a 2000-01-01 00:00:00 1 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_no_idx` t0 left join `auto_test_remote`.`ta_r_auto_inc` t1 on ((t1.`a` = t0.`a`) and (t0.`a` is not null)) left join `auto_test_remote`.`ta_r_3` t2 on (t2.`c` = t1.`c`) left join `auto_test_remote`.`ta_r` t3 on ((t3.`b` = t2.`b`) and (t2.`b` is not null)) where 1 order by t0.`a` desc +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; +a b date_format(c, '%Y-%m-%d %H:%i:%s') +1 a 2000-01-01 00:00:00 +2 b 2000-01-02 00:00:00 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/direct_left_right_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_left_right_join_nullable.result new file mode 100644 index 00000000000..f3c6e189444 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/direct_left_right_join_nullable.result @@ -0,0 +1,113 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +test select 1 +connection master_1; +SELECT 1; +1 +1 +connection child2_1; +SELECT 1; +1 +1 + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_DROP_TABLES6 +CHILD2_1_DROP_TABLES4 +CHILD2_1_DROP_TABLES3 +CHILD2_1_CREATE_TABLES +CHILD2_1_CREATE_TABLES6 +CHILD2_1_CREATE_TABLES4 +CHILD2_1_CREATE_TABLES3 +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1 +CREATE TABLE tbl_c ( +a INT AUTO_INCREMENT, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b), +KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1 +CREATE TABLE tbl_d ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1 +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +select test +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.a, c.b, c.c, d.a FROM tbl_a a left join tbl_b b on a.a = b.a left join tbl_c c on b.c = c.c right join tbl_d d on c.b = d.b ORDER BY d.a DESC; +a b c a +NULL NULL NULL 5 +NULL NULL NULL 4 +NULL NULL NULL 3 +2 b 2000-01-02 00:00:00 2 +1 a 2000-01-01 00:00:00 1 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_no_idx` t3 left join (`auto_test_remote`.`ta_r_auto_inc` t2 join `auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r` t0) on ((t2.`b` = t3.`b`) and (t2.`c` = t1.`c`) and (t0.`a` = t1.`a`) and (t1.`a` is not null) and (t3.`b` is not null)) where 1 order by t3.`a` desc +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; +a b date_format(c, '%Y-%m-%d %H:%i:%s') +1 a 2000-01-01 00:00:00 +2 b 2000-01-02 00:00:00 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/direct_left_right_left_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_left_right_left_join_nullable.result new file mode 100644 index 00000000000..88205fb0f65 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/direct_left_right_left_join_nullable.result @@ -0,0 +1,112 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +test select 1 +connection master_1; +SELECT 1; +1 +1 +connection child2_1; +SELECT 1; +1 +1 + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_DROP_TABLES6 +CHILD2_1_DROP_TABLES4 +CHILD2_1_DROP_TABLES3 +CHILD2_1_CREATE_TABLES +CHILD2_1_CREATE_TABLES6 +CHILD2_1_CREATE_TABLES4 +CHILD2_1_CREATE_TABLES3 +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1 +CREATE TABLE tbl_c ( +a INT AUTO_INCREMENT, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b), +KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1 +CREATE TABLE tbl_d ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1 +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +select test +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.a, c.b, c.c, d.a FROM tbl_a a left join tbl_b b on a.a = b.a right join tbl_c c on b.c = c.c left join tbl_d d on c.b = d.b ORDER BY d.a DESC; +a b c a +NULL d 2000-01-04 00:00:00 4 +NULL c 2000-01-03 00:00:00 3 +2 b 2000-01-02 00:00:00 2 +1 a 2000-01-01 00:00:00 1 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_auto_inc` t2 left join (`auto_test_remote`.`ta_r_3` t1 join `auto_test_remote`.`ta_r` t0) on ((t1.`c` = t2.`c`) and (t0.`a` = t1.`a`) and (t1.`a` is not null)) left join `auto_test_remote`.`ta_r_no_idx` t3 on (t3.`b` = t2.`b`) where 1 order by t3.`a` desc +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; +a b date_format(c, '%Y-%m-%d %H:%i:%s') +1 a 2000-01-01 00:00:00 +2 b 2000-01-02 00:00:00 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/direct_right_join.result b/storage/spider/mysql-test/spider/r/direct_right_join.result new file mode 100644 index 00000000000..8edfb682292 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/direct_right_join.result @@ -0,0 +1,108 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +test select 1 +connection master_1; +SELECT 1; +1 +1 +connection child2_1; +SELECT 1; +1 +1 + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_DROP_TABLES6 +CHILD2_1_DROP_TABLES5 +CHILD2_1_CREATE_TABLES +CHILD2_1_CREATE_TABLES6 +CHILD2_1_CREATE_TABLES5 +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +PRIMARY KEY(a), +KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1 +CREATE TABLE tbl_c ( +a INT AUTO_INCREMENT, +b INT DEFAULT 10, +c INT DEFAULT 11, +PRIMARY KEY(a), +KEY idx1(b), +KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT4_2_1 +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_c values (1,10,100),(2,20,200),(3,30,300),(4,40,400),(5,50,500); + +select test +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.a, c.b, c.c FROM tbl_a a right join tbl_b b on a.a = b.a right join tbl_c c on a.a = c.a ORDER BY a.b DESC; +a b c +5 50 500 +4 40 400 +3 30 300 +2 20 200 +1 10 100 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`b` `b`,t0.`a` `a`,t2.`b` `b`,t2.`c` `c` from `auto_test_remote`.`ta_r_int` t2 left join (`auto_test_remote`.`ta_r` t0 join `auto_test_remote`.`ta_r_3` t1) on ((t0.`a` = t2.`a`) and (t1.`a` = t2.`a`)) where 1 order by t0.`b` desc +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; +a b date_format(c, '%Y-%m-%d %H:%i:%s') +1 a 2000-01-01 00:00:00 +2 b 2000-01-02 00:00:00 +3 c 2000-01-03 00:00:00 +4 d 2000-01-04 00:00:00 +5 e 2000-01-05 00:00:00 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/direct_right_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_right_join_nullable.result new file mode 100644 index 00000000000..a05781cb6d6 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/direct_right_join_nullable.result @@ -0,0 +1,113 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +test select 1 +connection master_1; +SELECT 1; +1 +1 +connection child2_1; +SELECT 1; +1 +1 + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_DROP_TABLES6 +CHILD2_1_DROP_TABLES4 +CHILD2_1_DROP_TABLES3 +CHILD2_1_CREATE_TABLES +CHILD2_1_CREATE_TABLES6 +CHILD2_1_CREATE_TABLES4 +CHILD2_1_CREATE_TABLES3 +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1 +CREATE TABLE tbl_c ( +a INT AUTO_INCREMENT, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b), +KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1 +CREATE TABLE tbl_d ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1 +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +select test +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.a, c.b, c.c, d.a FROM tbl_a a right join tbl_b b on a.a = b.a right join tbl_c c on b.c = c.c right join tbl_d d on c.b = d.b ORDER BY d.a DESC; +a b c a +NULL NULL NULL 5 +NULL d 2000-01-04 00:00:00 4 +NULL c 2000-01-03 00:00:00 3 +2 b 2000-01-02 00:00:00 2 +1 a 2000-01-01 00:00:00 1 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_no_idx` t3 left join `auto_test_remote`.`ta_r_auto_inc` t2 on ((t2.`b` = t3.`b`) and (t3.`b` is not null)) left join `auto_test_remote`.`ta_r_3` t1 on (t1.`c` = t2.`c`) left join `auto_test_remote`.`ta_r` t0 on ((t0.`a` = t1.`a`) and (t1.`a` is not null)) where 1 order by t3.`a` desc +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; +a b date_format(c, '%Y-%m-%d %H:%i:%s') +1 a 2000-01-01 00:00:00 +2 b 2000-01-02 00:00:00 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/direct_right_left_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_right_left_join_nullable.result new file mode 100644 index 00000000000..25e0913ba06 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/direct_right_left_join_nullable.result @@ -0,0 +1,112 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +test select 1 +connection master_1; +SELECT 1; +1 +1 +connection child2_1; +SELECT 1; +1 +1 + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_DROP_TABLES6 +CHILD2_1_DROP_TABLES4 +CHILD2_1_DROP_TABLES3 +CHILD2_1_CREATE_TABLES +CHILD2_1_CREATE_TABLES6 +CHILD2_1_CREATE_TABLES4 +CHILD2_1_CREATE_TABLES3 +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1 +CREATE TABLE tbl_c ( +a INT AUTO_INCREMENT, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b), +KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1 +CREATE TABLE tbl_d ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1 +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +select test +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.a, c.b, c.c, d.a FROM tbl_a a right join tbl_b b on a.a = b.a right join tbl_c c on b.c = c.c left join tbl_d d on c.b = d.b ORDER BY d.a DESC; +a b c a +NULL d 2000-01-04 00:00:00 4 +NULL c 2000-01-03 00:00:00 3 +2 b 2000-01-02 00:00:00 2 +1 a 2000-01-01 00:00:00 1 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_auto_inc` t2 left join `auto_test_remote`.`ta_r_3` t1 on (t1.`c` = t2.`c`) left join `auto_test_remote`.`ta_r` t0 on ((t0.`a` = t1.`a`) and (t1.`a` is not null)) left join `auto_test_remote`.`ta_r_no_idx` t3 on (t3.`b` = t2.`b`) where 1 order by t3.`a` desc +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; +a b date_format(c, '%Y-%m-%d %H:%i:%s') +1 a 2000-01-01 00:00:00 +2 b 2000-01-02 00:00:00 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/direct_right_left_right_join_nullable.result b/storage/spider/mysql-test/spider/r/direct_right_left_right_join_nullable.result new file mode 100644 index 00000000000..48cd9c2c75f --- /dev/null +++ b/storage/spider/mysql-test/spider/r/direct_right_left_right_join_nullable.result @@ -0,0 +1,113 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +test select 1 +connection master_1; +SELECT 1; +1 +1 +connection child2_1; +SELECT 1; +1 +1 + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_DROP_TABLES6 +CHILD2_1_DROP_TABLES4 +CHILD2_1_DROP_TABLES3 +CHILD2_1_CREATE_TABLES +CHILD2_1_CREATE_TABLES6 +CHILD2_1_CREATE_TABLES4 +CHILD2_1_CREATE_TABLES3 +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1 +CREATE TABLE tbl_c ( +a INT AUTO_INCREMENT, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10', +KEY idx0(a), +KEY idx1(b), +KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1 +CREATE TABLE tbl_d ( +a INT DEFAULT 10, +b CHAR(1) DEFAULT 'c', +c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1 +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +select test +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.a, c.b, c.c, d.a FROM tbl_a a right join tbl_b b on a.a = b.a left join tbl_c c on b.c = c.c right join tbl_d d on c.b = d.b ORDER BY d.a DESC; +a b c a +NULL NULL NULL 5 +NULL NULL NULL 4 +NULL c 2000-01-03 00:00:00 3 +2 b 2000-01-02 00:00:00 2 +1 a 2000-01-01 00:00:00 1 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`a` `a`,t2.`b` `b`,t2.`c` `c`,t3.`a` `a` from `auto_test_remote`.`ta_r_no_idx` t3 left join (`auto_test_remote`.`ta_r_auto_inc` t2 join `auto_test_remote`.`ta_r_3` t1 left join `auto_test_remote`.`ta_r` t0 on ((t0.`a` = t1.`a`) and (t1.`a` is not null))) on ((t2.`b` = t3.`b`) and (t2.`c` = t1.`c`) and (t3.`b` is not null)) where 1 order by t3.`a` desc +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT a, b, date_format(c, '%Y-%m-%d %H:%i:%s') FROM ta_r ORDER BY a; +a b date_format(c, '%Y-%m-%d %H:%i:%s') +1 a 2000-01-01 00:00:00 +2 b 2000-01-02 00:00:00 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/show_system_tables.result b/storage/spider/mysql-test/spider/r/show_system_tables.result new file mode 100644 index 00000000000..831d4578efe --- /dev/null +++ b/storage/spider/mysql-test/spider/r/show_system_tables.result @@ -0,0 +1,37 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +Show system tables on the Spider node +connection master_1; +SELECT table_name, engine FROM information_schema.tables +WHERE table_schema = 'mysql' AND table_name like '%spider_%'; +table_name engine +spider_link_failed_log MyISAM +spider_link_mon_servers MyISAM +spider_table_crd MyISAM +spider_table_position_for_recovery MyISAM +spider_table_sts MyISAM +spider_tables MyISAM +spider_xa MyISAM +spider_xa_failed_log MyISAM +spider_xa_member MyISAM + +deinit +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/t/direct_join_using.test b/storage/spider/mysql-test/spider/t/direct_join_using.test new file mode 100644 index 00000000000..819e56ff21c --- /dev/null +++ b/storage/spider/mysql-test/spider/t/direct_join_using.test @@ -0,0 +1,197 @@ +--source ../include/direct_join_using_init.inc + +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo test select 1 +--connection master_1 +SELECT 1; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + SELECT 1; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_DROP_TABLES6; + echo CHILD2_1_DROP_TABLES5; + echo CHILD2_1_CREATE_TABLES; + echo CHILD2_1_CREATE_TABLES6; + echo CHILD2_1_CREATE_TABLES5; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + eval $CHILD2_1_DROP_TABLES6; + eval $CHILD2_1_DROP_TABLES5; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + eval $CHILD2_1_CREATE_TABLES6; + eval $CHILD2_1_CREATE_TABLES5; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + PRIMARY KEY(a), + KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + PRIMARY KEY(a), + KEY idx1(b) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1; +eval CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1; +echo CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b INT DEFAULT 10, + c INT DEFAULT 11, + PRIMARY KEY(a), + KEY idx1(b), + KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT4_2_1; +eval CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b INT DEFAULT 10, + c INT DEFAULT 11, + PRIMARY KEY(a), + KEY idx1(b), + KEY idx2(c) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT4_2_1; +--enable_query_log +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_c values (1,10,100),(2,20,200),(3,30,300),(4,40,400),(5,50,500); + +--echo +--echo select test +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +SELECT a.a, c.b, c.c FROM tbl_a a join tbl_b b using(a) join tbl_c c using(a) ORDER BY a.b DESC; + +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/direct_join_using_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/direct_left_join.test b/storage/spider/mysql-test/spider/t/direct_left_join.test new file mode 100644 index 00000000000..e09b6a12488 --- /dev/null +++ b/storage/spider/mysql-test/spider/t/direct_left_join.test @@ -0,0 +1,197 @@ +--source ../include/direct_left_join_init.inc + +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo test select 1 +--connection master_1 +SELECT 1; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + SELECT 1; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_DROP_TABLES6; + echo CHILD2_1_DROP_TABLES5; + echo CHILD2_1_CREATE_TABLES; + echo CHILD2_1_CREATE_TABLES6; + echo CHILD2_1_CREATE_TABLES5; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + eval $CHILD2_1_DROP_TABLES6; + eval $CHILD2_1_DROP_TABLES5; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + eval $CHILD2_1_CREATE_TABLES6; + eval $CHILD2_1_CREATE_TABLES5; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + PRIMARY KEY(a), + KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + PRIMARY KEY(a), + KEY idx1(b) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1; +eval CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1; +echo CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b INT DEFAULT 10, + c INT DEFAULT 11, + PRIMARY KEY(a), + KEY idx1(b), + KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT4_2_1; +eval CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b INT DEFAULT 10, + c INT DEFAULT 11, + PRIMARY KEY(a), + KEY idx1(b), + KEY idx2(c) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT4_2_1; +--enable_query_log +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_c values (1,10,100),(2,20,200),(3,30,300),(4,40,400),(5,50,500); + +--echo +--echo select test +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +SELECT a.a, c.b, c.c FROM tbl_a a left join tbl_b b on a.a = b.a left join tbl_c c on a.a = c.a ORDER BY a.b DESC; + +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/direct_left_join_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/direct_left_join_nullable.test b/storage/spider/mysql-test/spider/t/direct_left_join_nullable.test new file mode 100644 index 00000000000..dc67a01b4b2 --- /dev/null +++ b/storage/spider/mysql-test/spider/t/direct_left_join_nullable.test @@ -0,0 +1,212 @@ +--source ../include/direct_left_join_nullable_init.inc + +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo test select 1 +--connection master_1 +SELECT 1; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + SELECT 1; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_DROP_TABLES6; + echo CHILD2_1_DROP_TABLES4; + echo CHILD2_1_DROP_TABLES3; + echo CHILD2_1_CREATE_TABLES; + echo CHILD2_1_CREATE_TABLES6; + echo CHILD2_1_CREATE_TABLES4; + echo CHILD2_1_CREATE_TABLES3; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + eval $CHILD2_1_DROP_TABLES6; + eval $CHILD2_1_DROP_TABLES4; + eval $CHILD2_1_DROP_TABLES3; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + eval $CHILD2_1_CREATE_TABLES6; + eval $CHILD2_1_CREATE_TABLES4; + eval $CHILD2_1_CREATE_TABLES3; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1; +eval CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1; +echo CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1; +eval CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT3_2_1; +echo CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1; +eval CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT2_2_1; +--enable_query_log +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +--echo +--echo select test +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +SELECT a.a, c.b, c.c, d.a FROM tbl_d a left join tbl_c b on a.a = b.a left join tbl_b c on b.c = c.c left join tbl_a d on c.b = d.b ORDER BY a.a DESC; + +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/direct_left_join_nullable_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/direct_left_right_join_nullable.test b/storage/spider/mysql-test/spider/t/direct_left_right_join_nullable.test new file mode 100644 index 00000000000..9d5a990e0ba --- /dev/null +++ b/storage/spider/mysql-test/spider/t/direct_left_right_join_nullable.test @@ -0,0 +1,212 @@ +--source ../include/direct_left_right_join_nullable_init.inc + +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo test select 1 +--connection master_1 +SELECT 1; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + SELECT 1; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_DROP_TABLES6; + echo CHILD2_1_DROP_TABLES4; + echo CHILD2_1_DROP_TABLES3; + echo CHILD2_1_CREATE_TABLES; + echo CHILD2_1_CREATE_TABLES6; + echo CHILD2_1_CREATE_TABLES4; + echo CHILD2_1_CREATE_TABLES3; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + eval $CHILD2_1_DROP_TABLES6; + eval $CHILD2_1_DROP_TABLES4; + eval $CHILD2_1_DROP_TABLES3; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + eval $CHILD2_1_CREATE_TABLES6; + eval $CHILD2_1_CREATE_TABLES4; + eval $CHILD2_1_CREATE_TABLES3; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1; +eval CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1; +echo CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1; +eval CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT3_2_1; +echo CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1; +eval CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT2_2_1; +--enable_query_log +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +--echo +--echo select test +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +SELECT a.a, c.b, c.c, d.a FROM tbl_a a left join tbl_b b on a.a = b.a left join tbl_c c on b.c = c.c right join tbl_d d on c.b = d.b ORDER BY d.a DESC; + +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/direct_left_right_join_nullable_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/direct_left_right_left_join_nullable.test b/storage/spider/mysql-test/spider/t/direct_left_right_left_join_nullable.test new file mode 100644 index 00000000000..90e3666957d --- /dev/null +++ b/storage/spider/mysql-test/spider/t/direct_left_right_left_join_nullable.test @@ -0,0 +1,212 @@ +--source ../include/direct_left_right_left_join_nullable_init.inc + +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo test select 1 +--connection master_1 +SELECT 1; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + SELECT 1; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_DROP_TABLES6; + echo CHILD2_1_DROP_TABLES4; + echo CHILD2_1_DROP_TABLES3; + echo CHILD2_1_CREATE_TABLES; + echo CHILD2_1_CREATE_TABLES6; + echo CHILD2_1_CREATE_TABLES4; + echo CHILD2_1_CREATE_TABLES3; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + eval $CHILD2_1_DROP_TABLES6; + eval $CHILD2_1_DROP_TABLES4; + eval $CHILD2_1_DROP_TABLES3; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + eval $CHILD2_1_CREATE_TABLES6; + eval $CHILD2_1_CREATE_TABLES4; + eval $CHILD2_1_CREATE_TABLES3; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1; +eval CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1; +echo CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1; +eval CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT3_2_1; +echo CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1; +eval CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT2_2_1; +--enable_query_log +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +--echo +--echo select test +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +SELECT a.a, c.b, c.c, d.a FROM tbl_a a left join tbl_b b on a.a = b.a right join tbl_c c on b.c = c.c left join tbl_d d on c.b = d.b ORDER BY d.a DESC; + +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/direct_left_right_left_join_nullable_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/direct_right_join.test b/storage/spider/mysql-test/spider/t/direct_right_join.test new file mode 100644 index 00000000000..0c0496651d6 --- /dev/null +++ b/storage/spider/mysql-test/spider/t/direct_right_join.test @@ -0,0 +1,197 @@ +--source ../include/direct_right_join_init.inc + +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo test select 1 +--connection master_1 +SELECT 1; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + SELECT 1; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_DROP_TABLES6; + echo CHILD2_1_DROP_TABLES5; + echo CHILD2_1_CREATE_TABLES; + echo CHILD2_1_CREATE_TABLES6; + echo CHILD2_1_CREATE_TABLES5; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + eval $CHILD2_1_DROP_TABLES6; + eval $CHILD2_1_DROP_TABLES5; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + eval $CHILD2_1_CREATE_TABLES6; + eval $CHILD2_1_CREATE_TABLES5; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + PRIMARY KEY(a), + KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + PRIMARY KEY(a), + KEY idx1(b) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1; +eval CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1; +echo CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b INT DEFAULT 10, + c INT DEFAULT 11, + PRIMARY KEY(a), + KEY idx1(b), + KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT4_2_1; +eval CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b INT DEFAULT 10, + c INT DEFAULT 11, + PRIMARY KEY(a), + KEY idx1(b), + KEY idx2(c) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT4_2_1; +--enable_query_log +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); +insert into tbl_c values (1,10,100),(2,20,200),(3,30,300),(4,40,400),(5,50,500); + +--echo +--echo select test +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +SELECT a.a, c.b, c.c FROM tbl_a a right join tbl_b b on a.a = b.a right join tbl_c c on a.a = c.a ORDER BY a.b DESC; + +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/direct_right_join_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/direct_right_join_nullable.test b/storage/spider/mysql-test/spider/t/direct_right_join_nullable.test new file mode 100644 index 00000000000..3ab4a30ea84 --- /dev/null +++ b/storage/spider/mysql-test/spider/t/direct_right_join_nullable.test @@ -0,0 +1,212 @@ +--source ../include/direct_right_join_nullable_init.inc + +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo test select 1 +--connection master_1 +SELECT 1; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + SELECT 1; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_DROP_TABLES6; + echo CHILD2_1_DROP_TABLES4; + echo CHILD2_1_DROP_TABLES3; + echo CHILD2_1_CREATE_TABLES; + echo CHILD2_1_CREATE_TABLES6; + echo CHILD2_1_CREATE_TABLES4; + echo CHILD2_1_CREATE_TABLES3; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + eval $CHILD2_1_DROP_TABLES6; + eval $CHILD2_1_DROP_TABLES4; + eval $CHILD2_1_DROP_TABLES3; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + eval $CHILD2_1_CREATE_TABLES6; + eval $CHILD2_1_CREATE_TABLES4; + eval $CHILD2_1_CREATE_TABLES3; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1; +eval CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1; +echo CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1; +eval CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT3_2_1; +echo CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1; +eval CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT2_2_1; +--enable_query_log +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +--echo +--echo select test +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +SELECT a.a, c.b, c.c, d.a FROM tbl_a a right join tbl_b b on a.a = b.a right join tbl_c c on b.c = c.c right join tbl_d d on c.b = d.b ORDER BY d.a DESC; + +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/direct_right_join_nullable_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/direct_right_left_join_nullable.test b/storage/spider/mysql-test/spider/t/direct_right_left_join_nullable.test new file mode 100644 index 00000000000..fefe255890d --- /dev/null +++ b/storage/spider/mysql-test/spider/t/direct_right_left_join_nullable.test @@ -0,0 +1,212 @@ +--source ../include/direct_right_left_join_nullable_init.inc + +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo test select 1 +--connection master_1 +SELECT 1; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + SELECT 1; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_DROP_TABLES6; + echo CHILD2_1_DROP_TABLES4; + echo CHILD2_1_DROP_TABLES3; + echo CHILD2_1_CREATE_TABLES; + echo CHILD2_1_CREATE_TABLES6; + echo CHILD2_1_CREATE_TABLES4; + echo CHILD2_1_CREATE_TABLES3; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + eval $CHILD2_1_DROP_TABLES6; + eval $CHILD2_1_DROP_TABLES4; + eval $CHILD2_1_DROP_TABLES3; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + eval $CHILD2_1_CREATE_TABLES6; + eval $CHILD2_1_CREATE_TABLES4; + eval $CHILD2_1_CREATE_TABLES3; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1; +eval CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1; +echo CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1; +eval CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT3_2_1; +echo CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1; +eval CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT2_2_1; +--enable_query_log +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +--echo +--echo select test +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +SELECT a.a, c.b, c.c, d.a FROM tbl_a a right join tbl_b b on a.a = b.a right join tbl_c c on b.c = c.c left join tbl_d d on c.b = d.b ORDER BY d.a DESC; + +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/direct_right_left_join_nullable_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/direct_right_left_right_join_nullable.test b/storage/spider/mysql-test/spider/t/direct_right_left_right_join_nullable.test new file mode 100644 index 00000000000..48882d27939 --- /dev/null +++ b/storage/spider/mysql-test/spider/t/direct_right_left_right_join_nullable.test @@ -0,0 +1,212 @@ +--source ../include/direct_right_left_right_join_nullable_init.inc + +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo test select 1 +--connection master_1 +SELECT 1; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + SELECT 1; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_DROP_TABLES6; + echo CHILD2_1_DROP_TABLES4; + echo CHILD2_1_DROP_TABLES3; + echo CHILD2_1_CREATE_TABLES; + echo CHILD2_1_CREATE_TABLES6; + echo CHILD2_1_CREATE_TABLES4; + echo CHILD2_1_CREATE_TABLES3; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + eval $CHILD2_1_DROP_TABLES6; + eval $CHILD2_1_DROP_TABLES4; + eval $CHILD2_1_DROP_TABLES3; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + eval $CHILD2_1_CREATE_TABLES6; + eval $CHILD2_1_CREATE_TABLES4; + eval $CHILD2_1_CREATE_TABLES3; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT5_2_1; +eval CREATE TABLE tbl_b ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT5_2_1; +echo CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT3_2_1; +eval CREATE TABLE tbl_c ( + a INT AUTO_INCREMENT, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10', + KEY idx0(a), + KEY idx1(b), + KEY idx2(c) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT3_2_1; +echo CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT2_2_1; +eval CREATE TABLE tbl_d ( + a INT DEFAULT 10, + b CHAR(1) DEFAULT 'c', + c DATETIME DEFAULT '1999-10-10 10:10:10' +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT2_2_1; +--enable_query_log +insert into tbl_a values (1,'a','2000/01/01'),(2,'b','2000/01/02'); +insert into tbl_b values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'); +insert into tbl_c values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'); +insert into tbl_d values (1,'a','2000/01/01'),(2,'b','2000/01/02'),(3,'c','2000/01/03'),(4,'d','2000/01/04'),(5,'e','2000/01/05'); + +--echo +--echo select test +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +SELECT a.a, c.b, c.c, d.a FROM tbl_a a right join tbl_b b on a.a = b.a left join tbl_c c on b.c = c.c right join tbl_d d on c.b = d.b ORDER BY d.a DESC; + +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/direct_right_left_right_join_nullable_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/show_system_tables.test b/storage/spider/mysql-test/spider/t/show_system_tables.test new file mode 100644 index 00000000000..ae8259b01bc --- /dev/null +++ b/storage/spider/mysql-test/spider/t/show_system_tables.test @@ -0,0 +1,26 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings + +--echo +--echo Show system tables on the Spider node +--connection master_1 +--sorted_result +SELECT table_name, engine FROM information_schema.tables + WHERE table_schema = 'mysql' AND table_name like '%spider_%'; + +--echo +--echo deinit +--disable_warnings +--disable_query_log +--disable_result_log +--source test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings +--echo +--echo end of test diff --git a/storage/spider/scripts/install_spider.sql b/storage/spider/scripts/install_spider.sql index c5a86caa219..904288f4237 100644 --- a/storage/spider/scripts/install_spider.sql +++ b/storage/spider/scripts/install_spider.sql @@ -1,4 +1,4 @@ -# Copyright (C) 2010-2016 Kentoku Shiba +# Copyright (C) 2010-2018 Kentoku Shiba # # 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 @@ -167,8 +167,8 @@ drop procedure if exists mysql.spider_fix_system_tables; delimiter // create procedure mysql.spider_fix_one_table (tab_name char(255) charset utf8 collate utf8_bin, - test_col_name char(255) charset utf8 collate utf8_bin, - _sql text charset utf8 collate utf8_bin) + test_col_name char(255) charset utf8 collate utf8_bin, + _sql text charset utf8 collate utf8_bin) begin set @col_exists := 0; select 1 into @col_exists from INFORMATION_SCHEMA.COLUMNS @@ -184,6 +184,13 @@ end;// create procedure mysql.spider_fix_system_tables() begin + select substring_index(substring_index(version(), '-', 2), '-', -1) + into @server_name; + select substring_index(version(), '.', 1) + into @server_major_version; + select substring_index(substring_index(version(), '.', 2), '.', -1) + into @server_minor_version; + -- Fix for 0.5 call mysql.spider_fix_one_table('spider_tables', 'server', 'alter table mysql.spider_tables @@ -400,6 +407,81 @@ begin alter table mysql.spider_table_crd modify table_name char(199) not null default ''; end if; + + -- Fix for MariaDB 10.4: Crash-Safe system tables + if @server_name = 'MariaDB' and + ( + @server_major_version > 10 or + ( + @server_major_version = 10 and + @server_minor_version >= 4 + ) + ) + then + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_link_failed_log'; + if @engine_name != 'Aria' then + alter table mysql.spider_link_failed_log + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_link_mon_servers'; + if @engine_name != 'Aria' then + alter table mysql.spider_link_mon_servers + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_table_crd'; + if @engine_name != 'Aria' then + alter table mysql.spider_table_crd + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_table_position_for_recovery'; + if @engine_name != 'Aria' then + alter table mysql.spider_table_position_for_recovery + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_table_sts'; + if @engine_name != 'Aria' then + alter table mysql.spider_table_sts + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_tables'; + if @engine_name != 'Aria' then + alter table mysql.spider_tables + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_xa'; + if @engine_name != 'Aria' then + alter table mysql.spider_xa + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_xa_failed_log'; + if @engine_name != 'Aria' then + alter table mysql.spider_xa_failed_log + engine=Aria transactional=1; + end if; + select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES + where TABLE_SCHEMA = 'mysql' + AND TABLE_NAME = 'spider_xa_member'; + if @engine_name != 'Aria' then + alter table mysql.spider_xa_member + engine=Aria transactional=1; + end if; + end if; end;// delimiter ; call mysql.spider_fix_system_tables; diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index 148ad43d337..d48ec1f2285 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -1439,9 +1439,10 @@ void spider_conn_queue_time_zone( DBUG_VOID_RETURN; } -void spider_conn_queue_UTC_time_zone(SPIDER_CONN *conn) -{ - DBUG_ENTER("spider_conn_queue_time_zone"); +void spider_conn_queue_UTC_time_zone( + SPIDER_CONN *conn +) { + DBUG_ENTER("spider_conn_queue_UTC_time_zone"); DBUG_PRINT("info", ("spider conn=%p", conn)); spider_conn_queue_time_zone(conn, UTC); DBUG_VOID_RETURN; diff --git a/storage/spider/spd_conn.h b/storage/spider/spd_conn.h index 998658c5353..0a9f99a1853 100644 --- a/storage/spider/spd_conn.h +++ b/storage/spider/spd_conn.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -13,8 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "tztime.h" - #define SPIDER_LOCK_MODE_NO_LOCK 0 #define SPIDER_LOCK_MODE_SHARED 1 #define SPIDER_LOCK_MODE_EXCLUSIVE 2 diff --git a/storage/spider/spd_copy_tables.cc b/storage/spider/spd_copy_tables.cc index 82c0c490147..8dd9d968b99 100644 --- a/storage/spider/spd_copy_tables.cc +++ b/storage/spider/spd_copy_tables.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2017 Kentoku Shiba +/* Copyright (C) 2009-2018 Kentoku Shiba 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 @@ -53,10 +53,10 @@ int spider_udf_set_copy_tables_param_default( if (!copy_tables->database) { DBUG_PRINT("info",("spider create default database")); - copy_tables->database_length = copy_tables->trx->thd->db.length; + copy_tables->database_length = SPIDER_THD_db_length(copy_tables->trx->thd); if ( !(copy_tables->database = spider_create_string( - copy_tables->trx->thd->db.str, + SPIDER_THD_db_str(copy_tables->trx->thd), copy_tables->database_length)) ) { my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); @@ -90,8 +90,7 @@ int spider_udf_set_copy_tables_param_default( start_ptr, TRUE, ¶m_string_parse))) \ copy_tables->SPIDER_PARAM_STR_LEN(param_name) = \ strlen(copy_tables->param_name); \ - else \ - { \ + else { \ error_num = param_string_parse.print_param_error(); \ goto error; \ } \ @@ -968,19 +967,25 @@ long long spider_copy_tables_body( goto error; table_list = ©_tables->spider_table_list; - table_list->db.str = copy_tables->spider_db_name; - table_list->db.length = copy_tables->spider_db_name_length; - table_list->alias.str = table_list->table_name.str = + SPIDER_TABLE_LIST_db_str(table_list) = copy_tables->spider_db_name; + SPIDER_TABLE_LIST_db_length(table_list) = copy_tables->spider_db_name_length; + SPIDER_TABLE_LIST_alias_str(table_list) = + SPIDER_TABLE_LIST_table_name_str(table_list) = copy_tables->spider_real_table_name; - table_list->table_name.length = copy_tables->spider_real_table_name_length; - table_list->alias.length= table_list->table_name.length; + SPIDER_TABLE_LIST_table_name_length(table_list) = + copy_tables->spider_real_table_name_length; +#ifdef SPIDER_use_LEX_CSTRING_for_database_tablename_alias + SPIDER_TABLE_LIST_alias_length(table_list) = + SPIDER_TABLE_LIST_table_name_length(table_list); +#endif table_list->lock_type = TL_READ; - DBUG_PRINT("info",("spider db=%s", table_list->db.str)); - DBUG_PRINT("info",("spider db_length=%zd", table_list->db.length)); - DBUG_PRINT("info",("spider table_name=%s", table_list->table_name.str)); + DBUG_PRINT("info",("spider db=%s", SPIDER_TABLE_LIST_db_str(table_list))); + DBUG_PRINT("info",("spider db_length=%zd", SPIDER_TABLE_LIST_db_length(table_list))); + DBUG_PRINT("info",("spider table_name=%s", + SPIDER_TABLE_LIST_table_name_str(table_list))); DBUG_PRINT("info",("spider table_name_length=%zd", - table_list->table_name.length)); + SPIDER_TABLE_LIST_table_name_length(table_list))); reprepare_observer_backup = thd->m_reprepare_observer; thd->m_reprepare_observer = NULL; copy_tables->trx->trx_start = TRUE; @@ -991,8 +996,8 @@ long long spider_copy_tables_body( #else table_list->mdl_request.init( MDL_key::TABLE, - table_list->db.str, - table_list->table_name.str, + SPIDER_TABLE_LIST_db_str(table_list), + SPIDER_TABLE_LIST_table_name_str(table_list), MDL_SHARED_READ, MDL_TRANSACTION ); @@ -1004,8 +1009,9 @@ long long spider_copy_tables_body( copy_tables->trx->updated_in_this_trx = FALSE; DBUG_PRINT("info",("spider trx->updated_in_this_trx=FALSE")); my_printf_error(ER_SPIDER_UDF_CANT_OPEN_TABLE_NUM, - ER_SPIDER_UDF_CANT_OPEN_TABLE_STR, MYF(0), table_list->db, - table_list->table_name); + ER_SPIDER_UDF_CANT_OPEN_TABLE_STR, MYF(0), + SPIDER_TABLE_LIST_db_str(table_list), + SPIDER_TABLE_LIST_table_name_str(table_list)); goto error; } thd->m_reprepare_observer = reprepare_observer_backup; @@ -1019,7 +1025,8 @@ long long spider_copy_tables_body( { my_printf_error(ER_SPIDER_UDF_COPY_TABLE_NEED_PK_NUM, ER_SPIDER_UDF_COPY_TABLE_NEED_PK_STR, MYF(0), - table_list->db, table_list->table_name); + SPIDER_TABLE_LIST_db_str(table_list), + SPIDER_TABLE_LIST_table_name_str(table_list)); goto error; } key_info = &table->key_info[table_share->primary_key]; diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index ac5701a8274..1e117b68728 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -77,7 +77,7 @@ pthread_mutex_t spider_open_conn_mutex; const char spider_dig_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; /* UTC time zone for timestamp columns */ -extern Time_zone *UTC; +Time_zone *UTC = 0; int spider_db_connect( const SPIDER_SHARE *share, @@ -1387,12 +1387,34 @@ int spider_db_unlock_tables( int spider_db_append_name_with_quote_str( spider_string *str, - char *name, + const char *name, uint dbton_id ) { - int error_num, length = strlen(name); - char *name_end, head_code; DBUG_ENTER("spider_db_append_name_with_quote_str"); + DBUG_RETURN(spider_db_append_name_with_quote_str_internal( + str, name, strlen(name), dbton_id)); +} + +int spider_db_append_name_with_quote_str( + spider_string *str, + LEX_CSTRING &name, + uint dbton_id +) { + DBUG_ENTER("spider_db_append_name_with_quote_str"); + DBUG_RETURN(spider_db_append_name_with_quote_str_internal( + str, name.str, name.length, dbton_id)); +} + +int spider_db_append_name_with_quote_str_internal( + spider_string *str, + const char *name, + int length, + uint dbton_id +) { + int error_num; + const char *name_end; + char head_code; + DBUG_ENTER("spider_db_append_name_with_quote_str_internal"); for (name_end = name + length; name < name_end; name += length) { head_code = *name; @@ -1695,8 +1717,13 @@ int spider_db_append_key_where_internal( if (sql_kind == SPIDER_SQL_KIND_HANDLER) { +#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name const char *key_name = key_info->name.str; - key_name_length = key_info->name.length; + key_name_length = key_info->name.length; +#else + const char *key_name = key_info->name; + key_name_length = strlen(key_name); +#endif if (str->reserve(SPIDER_SQL_READ_LEN + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + key_name_length)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -2876,7 +2903,7 @@ int spider_db_fetch_row( THD *thd = field->table->in_use; Time_zone *saved_time_zone = thd->variables.time_zone; DBUG_ENTER("spider_db_fetch_row"); - DBUG_PRINT("info", ("spider field_name %s", field->field_name.str)); + DBUG_PRINT("info", ("spider field_name %s", SPIDER_field_name_str(field))); DBUG_PRINT("info", ("spider fieldcharset %s", field->charset()->csname)); thd->variables.time_zone = UTC; @@ -3013,7 +3040,7 @@ int spider_db_fetch_table( dbug_tmp_use_all_columns(table, table->write_set); #endif DBUG_PRINT("info", ("spider bitmap is set %s", - (*field)->field_name.str)); + SPIDER_field_name_str(*field))); if ((error_num = spider_db_fetch_row(share, *field, row, ptr_diff))) DBUG_RETURN(error_num); @@ -3184,7 +3211,8 @@ int spider_db_fetch_key( my_bitmap_map *tmp_map = dbug_tmp_use_all_columns(table, table->write_set); #endif - DBUG_PRINT("info", ("spider bitmap is set %s", field->field_name.str)); + DBUG_PRINT("info", ("spider bitmap is set %s", + SPIDER_field_name_str(field))); if ((error_num = spider_db_fetch_row(share, field, row, ptr_diff))) DBUG_RETURN(error_num); @@ -3303,7 +3331,7 @@ int spider_db_fetch_minimum_columns( dbug_tmp_use_all_columns(table, table->write_set); #endif DBUG_PRINT("info", ("spider bitmap is set %s", - (*field)->field_name.str)); + SPIDER_field_name_str(*field))); if ((error_num = spider_db_fetch_row(share, *field, row, ptr_diff))) DBUG_RETURN(error_num); #ifndef DBUG_OFF @@ -4011,9 +4039,18 @@ int spider_db_store_result( DBUG_PRINT("info",("spider store result to temporary table")); DBUG_ASSERT(!current->result_tmp_tbl); +#ifdef SPIDER_use_LEX_CSTRING_for_Field_blob_constructor + LEX_CSTRING field_name1 = {STRING_WITH_LEN("a")}; + LEX_CSTRING field_name2 = {STRING_WITH_LEN("b")}; + LEX_CSTRING field_name3 = {STRING_WITH_LEN("c")}; + if (!(current->result_tmp_tbl = spider_mk_sys_tmp_table_for_result( + thd, table, ¤t->result_tmp_tbl_prm, &field_name1, &field_name2, + &field_name3, &my_charset_bin))) +#else if (!(current->result_tmp_tbl = spider_mk_sys_tmp_table_for_result( thd, table, ¤t->result_tmp_tbl_prm, "a", "b", "c", &my_charset_bin))) +#endif { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } @@ -5324,7 +5361,7 @@ int spider_db_seek_tmp_table( dbug_tmp_use_all_columns(table, table->write_set); #endif DBUG_PRINT("info", ("spider bitmap is set %s", - (*field)->field_name.str)); + SPIDER_field_name_str(*field))); if ((error_num = spider_db_fetch_row(spider->share, *field, row, ptr_diff))) DBUG_RETURN(error_num); @@ -5411,7 +5448,8 @@ int spider_db_seek_tmp_key( my_bitmap_map *tmp_map = dbug_tmp_use_all_columns(table, table->write_set); #endif - DBUG_PRINT("info", ("spider bitmap is set %s", field->field_name.str)); + DBUG_PRINT("info", ("spider bitmap is set %s", + SPIDER_field_name_str(field))); if ((error_num = spider_db_fetch_row(spider->share, field, row, ptr_diff))) DBUG_RETURN(error_num); @@ -5502,7 +5540,7 @@ int spider_db_seek_tmp_minimum_columns( dbug_tmp_use_all_columns(table, table->write_set); #endif DBUG_PRINT("info", ("spider bitmap is set %s", - (*field)->field_name.str)); + SPIDER_field_name_str(*field))); if ((error_num = spider_db_fetch_row(spider->share, *field, row, ptr_diff))) DBUG_RETURN(error_num); @@ -5514,7 +5552,7 @@ int spider_db_seek_tmp_minimum_columns( else if (bitmap_is_set(table->read_set, (*field)->field_index)) { DBUG_PRINT("info", ("spider bitmap is cleared %s", - (*field)->field_name.str)); + SPIDER_field_name_str(*field))); bitmap_clear_bit(table->read_set, (*field)->field_index); } } @@ -8478,11 +8516,14 @@ int spider_db_flush_logs( contains only one field; NULL otherwise. */ -Field *spider_db_find_field_in_item_list(Item **item_list, uint item_count, - uint start_item, spider_string *str, - const char *func_name, - int func_name_length) -{ +Field *spider_db_find_field_in_item_list( + Item **item_list, + uint item_count, + uint start_item, + spider_string *str, + const char *func_name, + int func_name_length +) { uint item_num; Item *item; Field *field = NULL; @@ -8530,11 +8571,17 @@ Field *spider_db_find_field_in_item_list(Item **item_list, uint item_count, @return Error code. */ -int spider_db_print_item_type(Item *item, Field *field, ha_spider *spider, - spider_string *str, const char *alias, - uint alias_length, uint dbton_id, - bool use_fields, spider_fields *fields) -{ +int spider_db_print_item_type( + Item *item, + Field *field, + ha_spider *spider, + spider_string *str, + const char *alias, + uint alias_length, + uint dbton_id, + bool use_fields, + spider_fields *fields +) { DBUG_ENTER("spider_db_print_item_type"); DBUG_PRINT("info",("spider COND type=%d", item->type())); @@ -8560,26 +8607,40 @@ int spider_db_print_item_type(Item *item, Field *field, ha_spider *spider, case Item::ROW_ITEM: DBUG_RETURN(spider_db_open_item_row((Item_row *) item, spider, str, alias, alias_length, dbton_id, use_fields, fields)); +#ifdef SPIDER_USE_CONST_ITEM_FOR_STRING_INT_REAL_DECIMAL_DATE_ITEM + case Item::CONST_ITEM: + { + switch (item->cmp_type()) { + case TIME_RESULT: + case STRING_RESULT: + DBUG_RETURN(spider_db_open_item_string(item, field, spider, str, + alias, alias_length, dbton_id, use_fields, fields)); + case INT_RESULT: + case REAL_RESULT: + case DECIMAL_RESULT: + DBUG_RETURN(spider_db_open_item_int(item, field, spider, str, + alias, alias_length, dbton_id, use_fields, fields)); + default: + DBUG_ASSERT(FALSE); + DBUG_RETURN(spider_db_print_item_type_default(item, spider, str)); + } + } +#else case Item::STRING_ITEM: DBUG_RETURN(spider_db_open_item_string(item, field, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); + alias, alias_length, dbton_id, use_fields, fields)); case Item::INT_ITEM: case Item::REAL_ITEM: case Item::DECIMAL_ITEM: DBUG_RETURN(spider_db_open_item_int(item, field, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); + alias, alias_length, dbton_id, use_fields, fields)); +#endif case Item::CACHE_ITEM: - DBUG_RETURN(spider_db_open_item_cache((Item_cache *) item, field, - spider, str, alias, alias_length, - dbton_id, use_fields, fields)); + DBUG_RETURN(spider_db_open_item_cache((Item_cache *) item, field, spider, + str, alias, alias_length, dbton_id, use_fields, fields)); case Item::INSERT_VALUE_ITEM: DBUG_RETURN(spider_db_open_item_insert_value((Item_insert_value *) item, - field, spider, str, - alias, alias_length, - dbton_id, - use_fields, fields)); + field, spider, str, alias, alias_length, dbton_id, use_fields, fields)); case Item::SUBSELECT_ITEM: case Item::TRIGGER_FIELD_ITEM: #ifdef SPIDER_HAS_EXPR_CACHE_ITEM @@ -8587,31 +8648,40 @@ int spider_db_print_item_type(Item *item, Field *field, ha_spider *spider, #endif DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); default: - THD *thd = spider->trx->thd; - SPIDER_SHARE *share = spider->share; - if (spider_param_skip_default_condition(thd, - share->skip_default_condition)) - DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); - if (str) - { - if (spider->share->access_charset->cset == system_charset_info->cset) - { -#if MYSQL_VERSION_ID < 50500 - item->print(str->get_str(), QT_IS); -#else - item->print(str->get_str(), QT_TO_SYSTEM_CHARSET); -#endif - } else { - item->print(str->get_str(), QT_ORDINARY); - } - str->mem_calc(); - } - break; + DBUG_RETURN(spider_db_print_item_type_default(item, spider, str)); } DBUG_RETURN(0); } +int spider_db_print_item_type_default( + Item *item, + ha_spider *spider, + spider_string *str +) { + DBUG_ENTER("spider_db_print_item_type_default"); + THD *thd = spider->trx->thd; + SPIDER_SHARE *share = spider->share; + if (spider_param_skip_default_condition(thd, + share->skip_default_condition)) + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); + if (str) + { + if (spider->share->access_charset->cset == system_charset_info->cset) + { +#if MYSQL_VERSION_ID < 50500 + item->print(str->get_str(), QT_IS); +#else + item->print(str->get_str(), QT_TO_SYSTEM_CHARSET); +#endif + } else { + item->print(str->get_str(), QT_ORDINARY); + } + str->mem_calc(); + } + DBUG_RETURN(0); +} + int spider_db_open_item_cond( Item_cond *item_cond, ha_spider *spider, @@ -8641,8 +8711,7 @@ restart_first: if (str) restart_pos = str->length(); if ((error_num = spider_db_print_item_type(item, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields))) + alias, alias_length, dbton_id, use_fields, fields))) { if ( str && @@ -8676,8 +8745,7 @@ restart_first: } if ((error_num = spider_db_print_item_type(item, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields))) + alias, alias_length, dbton_id, use_fields, fields))) { if ( str && @@ -8786,7 +8854,15 @@ int spider_db_open_item_ident( } if (str) { - field_name_length = item_ident->field_name.length; +#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name + if (item_ident->field_name.str) + field_name_length = item_ident->field_name.length; +#else + if (item_ident->field_name) + field_name_length = strlen(item_ident->field_name); +#endif + else + field_name_length = 0; if (share->access_charset->cset == system_charset_info->cset) { if (str->reserve(alias_length + @@ -8795,8 +8871,13 @@ int spider_db_open_item_ident( DBUG_RETURN(HA_ERR_OUT_OF_MEM); } str->q_append(alias, alias_length); +#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name if ((error_num = spider_dbton[dbton_id].db_util-> append_name(str, item_ident->field_name.str, field_name_length))) +#else + if ((error_num = spider_dbton[dbton_id].db_util-> + append_name(str, item_ident->field_name, field_name_length))) +#endif { DBUG_RETURN(error_num); } @@ -8804,9 +8885,15 @@ int spider_db_open_item_ident( if (str->reserve(alias_length)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(alias, alias_length); +#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name if ((error_num = spider_dbton[dbton_id].db_util-> append_name_with_charset(str, item_ident->field_name.str, field_name_length, system_charset_info))) +#else + if ((error_num = spider_dbton[dbton_id].db_util-> + append_name_with_charset(str, item_ident->field_name, + field_name_length, system_charset_info))) +#endif { DBUG_RETURN(error_num); } @@ -8891,31 +8978,50 @@ int spider_db_open_item_ref( DBUG_ENTER("spider_db_open_item_ref"); if (item_ref->ref) { +#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name if ( (*(item_ref->ref))->type() != Item::CACHE_ITEM && item_ref->ref_type() != Item_ref::VIEW_REF && !item_ref->table_name && item_ref->name.str && item_ref->alias_name_used - ) { + ) +#else + if ( + (*(item_ref->ref))->type() != Item::CACHE_ITEM && + item_ref->ref_type() != Item_ref::VIEW_REF && + !item_ref->table_name && + item_ref->name && + item_ref->alias_name_used + ) +#endif + { if (str) { +#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name uint length = item_ref->name.length; +#else + uint length = strlen(item_ref->name); +#endif if (str->reserve(length + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2)) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } +#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name if ((error_num = spider_dbton[dbton_id].db_util-> append_name(str, item_ref->name.str, length))) +#else + if ((error_num = spider_dbton[dbton_id].db_util-> + append_name(str, item_ref->name, length))) +#endif { DBUG_RETURN(error_num); } } DBUG_RETURN(0); } - DBUG_RETURN(spider_db_print_item_type(*(item_ref->ref), NULL, spider, - str, alias, alias_length, dbton_id, - use_fields, fields)); + DBUG_RETURN(spider_db_print_item_type(*(item_ref->ref), NULL, spider, str, + alias, alias_length, dbton_id, use_fields, fields)); } DBUG_RETURN(spider_db_open_item_ident((Item_ident *) item_ref, spider, str, alias, alias_length, dbton_id, use_fields, fields)); @@ -8945,8 +9051,7 @@ int spider_db_open_item_row( { item = item_row->element_index(roop_count); if ((error_num = spider_db_print_item_type(item, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields))) + alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) { @@ -8957,8 +9062,7 @@ int spider_db_open_item_row( } item = item_row->element_index(roop_count); if ((error_num = spider_db_print_item_type(item, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields))) + alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) { @@ -8987,12 +9091,17 @@ int spider_db_open_item_row( @return Error code. */ -int spider_db_open_item_string(Item *item, Field *field, ha_spider *spider, - spider_string *str, - const char *alias, uint alias_length, - uint dbton_id, - bool use_fields, spider_fields *fields) -{ +int spider_db_open_item_string( + Item *item, + Field *field, + ha_spider *spider, + spider_string *str, + const char *alias, + uint alias_length, + uint dbton_id, + bool use_fields, + spider_fields *fields +) { int error_num = 0; DBUG_ENTER("spider_db_open_item_string"); @@ -9002,10 +9111,10 @@ int spider_db_open_item_string(Item *item, Field *field, ha_spider *spider, TABLE *table; my_bitmap_map *saved_map; Time_zone *saved_time_zone; + String str_value; char tmp_buf[MAX_FIELD_WIDTH]; spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset()); String *tmp_str2; - String str_value; tmp_str.init_calc_mem(126); if (!(tmp_str2 = item->val_str(tmp_str.get_str()))) @@ -9013,16 +9122,17 @@ int spider_db_open_item_string(Item *item, Field *field, ha_spider *spider, if (str->reserve(SPIDER_SQL_NULL_LEN)) { error_num = HA_ERR_OUT_OF_MEM; - goto error; + goto end; } str->q_append(SPIDER_SQL_NULL_STR, SPIDER_SQL_NULL_LEN); - } - else - { - if (field && field->type() == FIELD_TYPE_TIMESTAMP) - { + } else { + if ( + field && + field->type() == FIELD_TYPE_TIMESTAMP && + field->table->in_use->variables.time_zone != UTC + ) { /* - Store the string value in the field. This is necessary + Store the string value in the field. This is necessary when the statement contains more than one value for the same field. */ @@ -9039,15 +9149,14 @@ int spider_db_open_item_string(Item *item, Field *field, ha_spider *spider, if (!tmp_str2) { error_num = HA_ERR_OUT_OF_MEM; - goto error; + goto end; } } - if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 + - tmp_str2->length() * 2)) + tmp_str2->length() * 2)) { error_num = HA_ERR_OUT_OF_MEM; - goto error; + goto end; } if (!thd) tmp_str.mem_calc(); @@ -9056,12 +9165,12 @@ int spider_db_open_item_string(Item *item, Field *field, ha_spider *spider, if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN)) { error_num = HA_ERR_OUT_OF_MEM; - goto error; + goto end; } str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); } -error: +end: if (thd) { thd->variables.time_zone = saved_time_zone; @@ -9089,12 +9198,17 @@ error: @return Error code. */ -int spider_db_open_item_int(Item *item, Field *field, ha_spider *spider, - spider_string *str, - const char *alias, uint alias_length, - uint dbton_id, - bool use_fields, spider_fields *fields) -{ +int spider_db_open_item_int( + Item *item, + Field *field, + ha_spider *spider, + spider_string *str, + const char *alias, + uint alias_length, + uint dbton_id, + bool use_fields, + spider_fields *fields +) { int error_num = 0; DBUG_ENTER("spider_db_open_item_int"); @@ -9102,24 +9216,27 @@ int spider_db_open_item_int(Item *item, Field *field, ha_spider *spider, { THD *thd = NULL; TABLE *table; - bool print_quoted_string; my_bitmap_map *saved_map; Time_zone *saved_time_zone; + String str_value; + bool print_quoted_string; char tmp_buf[MAX_FIELD_WIDTH]; spider_string tmp_str(tmp_buf, MAX_FIELD_WIDTH, str->charset()); - String str_value; String *tmp_str2; tmp_str.init_calc_mem(127); if (!(tmp_str2 = item->val_str(tmp_str.get_str()))) { error_num = HA_ERR_OUT_OF_MEM; - goto error; + goto end; } tmp_str.mem_calc(); - if (field && field->type() == FIELD_TYPE_TIMESTAMP) - { + if ( + field && + field->type() == FIELD_TYPE_TIMESTAMP && + field->table->in_use->variables.time_zone != UTC + ) { /* Store the int value in the field. This is necessary when the statement contains more than one value for the @@ -9132,11 +9249,9 @@ int spider_db_open_item_int(Item *item, Field *field, ha_spider *spider, saved_time_zone = thd->variables.time_zone; thd->variables.time_zone = UTC; print_quoted_string = TRUE; - } - else - { + } else { #ifdef SPIDER_ITEM_HAS_CMP_TYPE - DBUG_PRINT("info", ("spider cmp_type=%u", item->cmp_type())); + DBUG_PRINT("info",("spider cmp_type=%u", item->cmp_type())); if (item->cmp_type() == TIME_RESULT) print_quoted_string = TRUE; else @@ -9154,23 +9269,24 @@ int spider_db_open_item_int(Item *item, Field *field, ha_spider *spider, if (!tmp_str2) { error_num = HA_ERR_OUT_OF_MEM; - goto error; + goto end; } } if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 + tmp_str2->length())) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); + { + error_num = HA_ERR_OUT_OF_MEM; + goto end; + } str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); str->append(*tmp_str2); str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); - } - else - { + } else { if (str->append(*tmp_str2)) error_num = HA_ERR_OUT_OF_MEM; } -error: +end: if (thd) { thd->variables.time_zone = saved_time_zone; @@ -9198,12 +9314,17 @@ error: @return Error code. */ -int spider_db_open_item_cache(Item_cache *item_cache, Field *field, - ha_spider *spider, spider_string *str, - const char *alias, uint alias_length, - uint dbton_id, - bool use_fields, spider_fields *fields) -{ +int spider_db_open_item_cache( + Item_cache *item_cache, + Field *field, + ha_spider *spider, + spider_string *str, + const char *alias, + uint alias_length, + uint dbton_id, + bool use_fields, + spider_fields *fields +) { DBUG_ENTER("spider_db_open_item_cache"); if (!item_cache->const_item()) DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); @@ -9213,8 +9334,7 @@ int spider_db_open_item_cache(Item_cache *item_cache, Field *field, { case STRING_RESULT: DBUG_RETURN(spider_db_open_item_string(item_cache, field, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); + alias, alias_length, dbton_id, use_fields, fields)); case ROW_RESULT: { int error_num; @@ -9229,11 +9349,9 @@ int spider_db_open_item_cache(Item_cache *item_cache, Field *field, for (roop_count = 0; roop_count < item_count; ++roop_count) { if ((error_num = spider_db_open_item_cache( - (Item_cache *) - item_cache_row->element_index(roop_count), - NULL, spider, str, alias, alias_length, - dbton_id, use_fields, fields))) - { + (Item_cache *) item_cache_row->element_index(roop_count), NULL, + spider, str, alias, alias_length, dbton_id, use_fields, fields + ))) { DBUG_RETURN(error_num); } if (str) @@ -9244,11 +9362,9 @@ int spider_db_open_item_cache(Item_cache *item_cache, Field *field, } } if ((error_num = spider_db_open_item_cache( - (Item_cache *) - item_cache_row->element_index(roop_count), - NULL, spider, str, alias, alias_length, - dbton_id, use_fields, fields))) - { + (Item_cache *) item_cache_row->element_index(roop_count), NULL, + spider, str, alias, alias_length, dbton_id, use_fields, fields + ))) { DBUG_RETURN(error_num); } if (str) @@ -9266,10 +9382,8 @@ int spider_db_open_item_cache(Item_cache *item_cache, Field *field, default: break; } - DBUG_RETURN(spider_db_open_item_int(item_cache, field, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); + alias, alias_length, dbton_id, use_fields, fields)); } /** @@ -9288,13 +9402,17 @@ int spider_db_open_item_cache(Item_cache *item_cache, Field *field, @return Error code. */ -int spider_db_open_item_insert_value(Item_insert_value *item_insert_value, - Field *field, ha_spider *spider, - spider_string *str, - const char *alias, uint alias_length, - uint dbton_id, - bool use_fields, spider_fields *fields) -{ +int spider_db_open_item_insert_value( + Item_insert_value *item_insert_value, + Field *field, + ha_spider *spider, + spider_string *str, + const char *alias, + uint alias_length, + uint dbton_id, + bool use_fields, + spider_fields *fields +) { int error_num; DBUG_ENTER("spider_db_open_item_insert_value"); @@ -9308,9 +9426,7 @@ int spider_db_open_item_insert_value(Item_insert_value *item_insert_value, str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); } if ((error_num = spider_db_print_item_type(item_insert_value->arg, field, - spider, str, alias, - alias_length, dbton_id, - use_fields, fields))) + spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) { @@ -9375,10 +9491,9 @@ int spider_db_append_update_columns( while ((field = fi++)) { value = vi++; - if ((error_num = spider_db_print_item_type((Item *) field, NULL, spider, - str, alias, alias_length, - dbton_id, - use_fields, fields))) + if ((error_num = spider_db_print_item_type( + (Item *) field, NULL, spider, str, alias, alias_length, dbton_id, + use_fields, fields))) { if ( error_num == ER_SPIDER_COND_SKIP_NUM && @@ -9396,12 +9511,9 @@ int spider_db_append_update_columns( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); } - if ((error_num = spider_db_print_item_type((Item *) value, - ((Item_field *) field)->field, - spider, str, - alias, alias_length, - dbton_id, - use_fields, fields))) + if ((error_num = spider_db_print_item_type( + (Item *) value, ((Item_field *) field)->field, spider, str, + alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) { @@ -10599,8 +10711,13 @@ int spider_db_udf_copy_key_row( ) { int error_num; DBUG_ENTER("spider_db_udf_copy_key_row"); +#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name if ((error_num = spider_db_append_name_with_quote_str(str, (char *) field->field_name.str, dbton_id))) +#else + if ((error_num = spider_db_append_name_with_quote_str(str, + (char *) field->field_name, dbton_id))) +#endif DBUG_RETURN(error_num); if (str->reserve(joint_length + *length + SPIDER_SQL_AND_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); diff --git a/storage/spider/spd_db_conn.h b/storage/spider/spd_db_conn.h index 879ab3540c1..6ff35b794cd 100644 --- a/storage/spider/spd_db_conn.h +++ b/storage/spider/spd_db_conn.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -412,7 +412,20 @@ int spider_db_unlock_tables( int spider_db_append_name_with_quote_str( spider_string *str, - char *name, + const char *name, + uint dbton_id +); + +int spider_db_append_name_with_quote_str( + spider_string *str, + LEX_CSTRING &name, + uint dbton_id +); + +int spider_db_append_name_with_quote_str_internal( + spider_string *str, + const char *name, + int length, uint dbton_id ); @@ -859,6 +872,12 @@ int spider_db_print_item_type( spider_fields *fields ); +int spider_db_print_item_type_default( + Item *item, + ha_spider *spider, + spider_string *str +); + int spider_db_open_item_cond( Item_cond *item_cond, ha_spider *spider, diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc index dc4b9dd25ec..412450b96f8 100644 --- a/storage/spider/spd_db_handlersocket.cc +++ b/storage/spider/spd_db_handlersocket.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2017 Kentoku Shiba +/* Copyright (C) 2012-2018 Kentoku Shiba 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 @@ -2755,10 +2755,10 @@ int spider_db_handlersocket_util::open_item_func( Item *item, **item_list = item_func->arguments(); uint roop_count, item_count = item_func->argument_count(), start_item = 0; const char *func_name = SPIDER_SQL_NULL_CHAR_STR, - *separete_str = SPIDER_SQL_NULL_CHAR_STR, + *separator_str = SPIDER_SQL_NULL_CHAR_STR, *last_str = SPIDER_SQL_NULL_CHAR_STR; int func_name_length = SPIDER_SQL_NULL_CHAR_LEN, - separete_str_length = SPIDER_SQL_NULL_CHAR_LEN, + separator_str_length = SPIDER_SQL_NULL_CHAR_LEN, last_str_length = SPIDER_SQL_NULL_CHAR_LEN; int use_pushdown_udf; bool merge_func = FALSE; @@ -2824,7 +2824,7 @@ int spider_db_handlersocket_util::open_item_func( ) { if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_int(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_int(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); } else if ( !strncasecmp("case", func_name, func_name_length) @@ -2840,7 +2840,7 @@ int spider_db_handlersocket_util::open_item_func( if (item_func_case->first_expr_num != -1) { if ((error_num = spider_db_print_item_type( - item_list[item_func_case->first_expr_num], spider, str, + item_list[item_func_case->first_expr_num], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -2854,7 +2854,7 @@ int spider_db_handlersocket_util::open_item_func( str->q_append(SPIDER_SQL_WHEN_STR, SPIDER_SQL_WHEN_LEN); } if ((error_num = spider_db_print_item_type( - item_list[roop_count], spider, str, + item_list[roop_count], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -2864,7 +2864,7 @@ int spider_db_handlersocket_util::open_item_func( str->q_append(SPIDER_SQL_THEN_STR, SPIDER_SQL_THEN_LEN); } if ((error_num = spider_db_print_item_type( - item_list[roop_count + 1], spider, str, + item_list[roop_count + 1], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -2877,7 +2877,7 @@ int spider_db_handlersocket_util::open_item_func( str->q_append(SPIDER_SQL_ELSE_STR, SPIDER_SQL_ELSE_LEN); } if ((error_num = spider_db_print_item_type( - item_list[item_func_case->else_expr_num], spider, str, + item_list[item_func_case->else_expr_num], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -2914,7 +2914,7 @@ int spider_db_handlersocket_util::open_item_func( ) { if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_string(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); } else if ( !strncasecmp("convert", func_name, func_name_length) @@ -2939,7 +2939,7 @@ int spider_db_handlersocket_util::open_item_func( ) { if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_string(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); } else if (func_name_length == 9 && !strncasecmp("isnottrue", func_name, func_name_length) @@ -2966,8 +2966,8 @@ int spider_db_handlersocket_util::open_item_func( } func_name = SPIDER_SQL_COMMA_STR; func_name_length = SPIDER_SQL_COMMA_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; break; } } else if (func_name_length == 12) @@ -3055,7 +3055,7 @@ int spider_db_handlersocket_util::open_item_func( { if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_string(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); } else if (!strncasecmp("timestampdiff", func_name, func_name_length)) { @@ -3118,7 +3118,7 @@ int spider_db_handlersocket_util::open_item_func( str->q_append(interval_str, interval_len); str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } - if ((error_num = spider_db_print_item_type(item_list[0], spider, + if ((error_num = spider_db_print_item_type(item_list[0], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -3127,7 +3127,7 @@ int spider_db_handlersocket_util::open_item_func( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } - if ((error_num = spider_db_print_item_type(item_list[1], spider, + if ((error_num = spider_db_print_item_type(item_list[1], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -3381,8 +3381,8 @@ int spider_db_handlersocket_util::open_item_func( func_name = spider_db_timefunc_interval_str[ item_date_add_interval->int_type]; func_name_length = strlen(func_name); - if ((error_num = spider_db_print_item_type(item_list[0], spider, str, - alias, alias_length, dbton_id, use_fields, fields))) + if ((error_num = spider_db_print_item_type(item_list[0], NULL, spider, + str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) { @@ -3398,8 +3398,8 @@ int spider_db_handlersocket_util::open_item_func( str->q_append(SPIDER_SQL_INTERVAL_STR, SPIDER_SQL_INTERVAL_LEN); } } - if ((error_num = spider_db_print_item_type(item_list[1], spider, str, - alias, alias_length, dbton_id, use_fields, fields))) + if ((error_num = spider_db_print_item_type(item_list[1], NULL, spider, + str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) { @@ -3421,15 +3421,15 @@ int spider_db_handlersocket_util::open_item_func( } func_name = SPIDER_SQL_COMMA_STR; func_name_length = SPIDER_SQL_COMMA_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; case Item_func::NOW_FUNC: if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_string(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); case Item_func::CHAR_TYPECAST_FUNC: DBUG_PRINT("info",("spider CHAR_TYPECAST_FUNC")); @@ -3555,15 +3555,15 @@ int spider_db_handlersocket_util::open_item_func( { func_name = SPIDER_SQL_NOT_IN_STR; func_name_length = SPIDER_SQL_NOT_IN_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; } else { func_name = SPIDER_SQL_IN_STR; func_name_length = SPIDER_SQL_IN_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; } @@ -3573,13 +3573,13 @@ int spider_db_handlersocket_util::open_item_func( { func_name = SPIDER_SQL_NOT_BETWEEN_STR; func_name_length = SPIDER_SQL_NOT_BETWEEN_LEN; - separete_str = SPIDER_SQL_AND_STR; - separete_str_length = SPIDER_SQL_AND_LEN; + separator_str = SPIDER_SQL_AND_STR; + separator_str_length = SPIDER_SQL_AND_LEN; } else { func_name = (char*) item_func->func_name(); func_name_length = strlen(func_name); - separete_str = SPIDER_SQL_AND_STR; - separete_str_length = SPIDER_SQL_AND_LEN; + separator_str = SPIDER_SQL_AND_STR; + separator_str_length = SPIDER_SQL_AND_LEN; } break; case Item_func::UDF_FUNC: @@ -3600,8 +3600,8 @@ int spider_db_handlersocket_util::open_item_func( } func_name = SPIDER_SQL_COMMA_STR; func_name_length = SPIDER_SQL_COMMA_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; @@ -3621,10 +3621,10 @@ int spider_db_handlersocket_util::open_item_func( if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (item_func->result_type() == STRING_RESULT) - DBUG_RETURN(spider_db_open_item_string(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); else - DBUG_RETURN(spider_db_open_item_int(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_int(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); case Item_func::FT_FUNC: if (spider_db_check_ft_idx(item_func, spider) == MAX_KEY) @@ -3636,8 +3636,8 @@ int spider_db_handlersocket_util::open_item_func( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_MATCH_STR, SPIDER_SQL_MATCH_LEN); } - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; @@ -3654,8 +3654,8 @@ int spider_db_handlersocket_util::open_item_func( } func_name = SPIDER_SQL_COMMA_STR; func_name_length = SPIDER_SQL_COMMA_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; @@ -3686,8 +3686,8 @@ int spider_db_handlersocket_util::open_item_func( } func_name = SPIDER_SQL_COMMA_STR; func_name_length = SPIDER_SQL_COMMA_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; @@ -3720,8 +3720,8 @@ int spider_db_handlersocket_util::open_item_func( } DBUG_PRINT("info",("spider func_name = %s", func_name)); DBUG_PRINT("info",("spider func_name_length = %d", func_name_length)); - DBUG_PRINT("info",("spider separete_str = %s", separete_str)); - DBUG_PRINT("info",("spider separete_str_length = %d", separete_str_length)); + DBUG_PRINT("info",("spider separator_str = %s", separator_str)); + DBUG_PRINT("info",("spider separator_str_length = %d", separator_str_length)); DBUG_PRINT("info",("spider last_str = %s", last_str)); DBUG_PRINT("info",("spider last_str_length = %d", last_str_length)); if (item_count) @@ -3730,13 +3730,13 @@ int spider_db_handlersocket_util::open_item_func( for (roop_count = start_item; roop_count < item_count; roop_count++) { item = item_list[roop_count]; - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (roop_count == 1) { - func_name = separete_str; - func_name_length = separete_str_length; + func_name = separator_str; + func_name_length = separator_str_length; } if (str) { @@ -3748,7 +3748,7 @@ int spider_db_handlersocket_util::open_item_func( } } item = item_list[roop_count]; - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -3762,7 +3762,7 @@ int spider_db_handlersocket_util::open_item_func( str->q_append(SPIDER_SQL_AGAINST_STR, SPIDER_SQL_AGAINST_LEN); } item = item_list[0]; - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -3850,7 +3850,7 @@ int spider_db_handlersocket_util::open_item_sum_func( for (roop_count = 0; roop_count < item_count; roop_count++) { item = args[roop_count]; - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -3861,7 +3861,7 @@ int spider_db_handlersocket_util::open_item_sum_func( } } item = args[roop_count]; - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -3902,8 +3902,11 @@ int spider_db_handlersocket_util::append_escaped_util( #ifdef SPIDER_HAS_GROUP_BY_HANDLER int spider_db_handlersocket_util::append_from_and_tables( + ha_spider *spider, spider_fields *fields, - spider_string *str + spider_string *str, + TABLE_LIST *table_list, + uint table_count ) { DBUG_ENTER("spider_db_handlersocket_util::append_from_and_tables"); DBUG_PRINT("info",("spider this=%p", this)); @@ -4209,7 +4212,7 @@ int spider_handlersocket_share::create_column_name_str() str->init_calc_mem(202); str->set_charset(spider_share->access_charset); if ((error_num = spider_db_append_name_with_quote_str(str, - (char *) (*field)->field_name.str, dbton_id))) + (*field)->field_name, dbton_id))) goto error; } DBUG_RETURN(0); diff --git a/storage/spider/spd_db_handlersocket.h b/storage/spider/spd_db_handlersocket.h index 19138b22e1a..3767f0f3fac 100644 --- a/storage/spider/spd_db_handlersocket.h +++ b/storage/spider/spd_db_handlersocket.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2017 Kentoku Shiba +/* Copyright (C) 2012-2018 Kentoku Shiba 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 @@ -119,8 +119,11 @@ public: ); #ifdef SPIDER_HAS_GROUP_BY_HANDLER int append_from_and_tables( + ha_spider *spider, spider_fields *fields, - spider_string *str + spider_string *str, + TABLE_LIST *table_list, + uint table_count ); int reappend_tables( spider_fields *fields, diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index d19306b1b1a..7f1148655e3 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -17,7 +17,6 @@ #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) #include "hstcpcli.hpp" #endif -#include "tztime.h" #define SPIDER_DBTON_SIZE 15 @@ -703,6 +702,8 @@ public: ); void set_pos_to_first_table_holder(); SPIDER_TABLE_HOLDER *get_next_table_holder(); + SPIDER_TABLE_HOLDER *get_table_holder(TABLE *table); + uint get_table_count(); int add_field(Field *field_arg); SPIDER_FIELD_HOLDER *create_field_holder(); void set_pos_to_first_field_holder(); @@ -888,8 +889,11 @@ public: ) = 0; #ifdef SPIDER_HAS_GROUP_BY_HANDLER virtual int append_from_and_tables( + ha_spider *spider, spider_fields *fields, - spider_string *str + spider_string *str, + TABLE_LIST *table_list, + uint table_count ) = 0; virtual int reappend_tables( spider_fields *fields, diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index ada9aa20821..8c17bc8970d 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2017 Kentoku Shiba +/* Copyright (C) 2012-2018 Kentoku Shiba 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 @@ -109,6 +109,15 @@ static const char *name_quote_str = SPIDER_SQL_NAME_QUOTE_STR; #define SPIDER_SQL_UNLOCK_TABLE_STR "unlock tables" #define SPIDER_SQL_UNLOCK_TABLE_LEN (sizeof(SPIDER_SQL_UNLOCK_TABLE_STR) - 1) +#define SPIDER_SQL_LEFT_JOIN_STR " left join " +#define SPIDER_SQL_LEFT_JOIN_LEN (sizeof(SPIDER_SQL_LEFT_JOIN_STR) - 1) +#define SPIDER_SQL_RIGHT_JOIN_STR " right join " +#define SPIDER_SQL_RIGHT_JOIN_LEN (sizeof(SPIDER_SQL_RIGHT_JOIN_STR) - 1) +#define SPIDER_SQL_JOIN_STR " join " +#define SPIDER_SQL_JOIN_LEN (sizeof(SPIDER_SQL_JOIN_STR) - 1) +#define SPIDER_SQL_ON_STR " on " +#define SPIDER_SQL_ON_LEN (sizeof(SPIDER_SQL_ON_STR) - 1) + #define SPIDER_SQL_SHOW_TABLE_STATUS_STR "show table status from " #define SPIDER_SQL_SHOW_TABLE_STATUS_LEN sizeof(SPIDER_SQL_SHOW_TABLE_STATUS_STR) - 1 #define SPIDER_SQL_SELECT_TABLES_STATUS_STR "select `table_rows`,`avg_row_length`,`data_length`,`max_data_length`,`index_length`,`auto_increment`,`create_time`,`update_time`,`check_time` from `information_schema`.`tables` where `table_schema` = " @@ -180,7 +189,7 @@ static const char *spider_db_timefunc_interval_str[] = }; /* UTC time zone for timestamp columns */ -Time_zone *UTC = 0; +extern Time_zone *UTC; int spider_mysql_init() { @@ -713,8 +722,8 @@ int spider_db_mysql_result::fetch_table_status( #ifdef SPIDER_HAS_TIME_STATUS my_time_status_init(&time_status); #endif - str_to_datetime(mysql_row[11], strlen(mysql_row[11]), &mysql_time, 0, - &time_status); + SPIDER_str_to_datetime(mysql_row[11], strlen(mysql_row[11]), + &mysql_time, 0, &time_status); #ifdef MARIADB_BASE_VERSION create_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -738,8 +747,8 @@ int spider_db_mysql_result::fetch_table_status( #ifdef SPIDER_HAS_TIME_STATUS my_time_status_init(&time_status); #endif - str_to_datetime(mysql_row[12], strlen(mysql_row[12]), &mysql_time, 0, - &time_status); + SPIDER_str_to_datetime(mysql_row[12], strlen(mysql_row[12]), + &mysql_time, 0, &time_status); #ifdef MARIADB_BASE_VERSION update_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -763,8 +772,8 @@ int spider_db_mysql_result::fetch_table_status( #ifdef SPIDER_HAS_TIME_STATUS my_time_status_init(&time_status); #endif - str_to_datetime(mysql_row[13], strlen(mysql_row[13]), &mysql_time, 0, - &time_status); + SPIDER_str_to_datetime(mysql_row[13], strlen(mysql_row[13]), + &mysql_time, 0, &time_status); #ifdef MARIADB_BASE_VERSION check_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -831,8 +840,8 @@ int spider_db_mysql_result::fetch_table_status( #ifdef SPIDER_HAS_TIME_STATUS my_time_status_init(&time_status); #endif - str_to_datetime(mysql_row[6], strlen(mysql_row[6]), &mysql_time, 0, - &time_status); + SPIDER_str_to_datetime(mysql_row[6], strlen(mysql_row[6]), + &mysql_time, 0, &time_status); #ifdef MARIADB_BASE_VERSION create_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -856,8 +865,8 @@ int spider_db_mysql_result::fetch_table_status( #ifdef SPIDER_HAS_TIME_STATUS my_time_status_init(&time_status); #endif - str_to_datetime(mysql_row[7], strlen(mysql_row[7]), &mysql_time, 0, - &time_status); + SPIDER_str_to_datetime(mysql_row[7], strlen(mysql_row[7]), + &mysql_time, 0, &time_status); #ifdef MARIADB_BASE_VERSION update_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -881,8 +890,8 @@ int spider_db_mysql_result::fetch_table_status( #ifdef SPIDER_HAS_TIME_STATUS my_time_status_init(&time_status); #endif - str_to_datetime(mysql_row[8], strlen(mysql_row[8]), &mysql_time, 0, - &time_status); + SPIDER_str_to_datetime(mysql_row[8], strlen(mysql_row[8]), + &mysql_time, 0, &time_status); #ifdef MARIADB_BASE_VERSION check_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -1524,7 +1533,7 @@ int spider_db_mysql_result::fetch_table_for_discover_table_structure( } DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - if (num_fields() != 18) + if (num_fields() < 18) { DBUG_PRINT("info",("spider num_fields != 18")); my_printf_error(ER_SPIDER_UNKNOWN_NUM, ER_SPIDER_UNKNOWN_STR, MYF(0)); @@ -3092,8 +3101,13 @@ void spider_db_mysql::set_dup_key_idx( key_name = spider->share->tgt_pk_names[all_link_idx]; key_name_length = spider->share->tgt_pk_names_lengths[all_link_idx]; } else { - key_name = table->s->key_info[roop_count].name.str; +#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name + key_name = table->s->key_info[roop_count].name.str; key_name_length = table->s->key_info[roop_count].name.length; +#else + key_name = table->s->key_info[roop_count].name; + key_name_length = strlen(key_name); +#endif } DBUG_PRINT("info",("spider key_name=%s", key_name)); if ( @@ -3212,8 +3226,7 @@ int spider_db_mysql_util::append_column_value( tmp_str.set_quick((char *) new_ptr + HA_KEY_BLOB_LENGTH, length, &my_charset_bin); ptr = tmp_str.get_str(); - } - else if (field->type() == MYSQL_TYPE_GEOMETRY) + } else if (field->type() == MYSQL_TYPE_GEOMETRY) { /* uint mlength = SIZEOF_STORED_DOUBLE, lcnt; @@ -3290,15 +3303,11 @@ int spider_db_mysql_util::append_column_value( tmp_str.q_append((char *) new_ptr + SIZEOF_STORED_DOUBLE * 3, SIZEOF_STORED_DOUBLE); ptr = tmp_str.get_str(); - } - else - { + } else { ptr = field->val_str(tmp_str.get_str(), new_ptr); tmp_str.mem_calc(); } - } - else - { + } else { ptr = field->val_str(tmp_str.get_str()); tmp_str.mem_calc(); } @@ -3350,8 +3359,7 @@ int spider_db_mysql_util::append_column_value( append_escaped_util(str, tmp_str2.get_str()) ) DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - else if (str->append(*ptr)) + } else if (str->append(*ptr)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -3621,7 +3629,7 @@ int spider_db_mysql_util::open_item_func( int error_num; Item *item, **item_list = item_func->arguments(); Field *field; - uint loop_count, item_count = item_func->argument_count(), start_item = 0; + uint roop_count, item_count = item_func->argument_count(), start_item = 0; const char *func_name = SPIDER_SQL_NULL_CHAR_STR, *separator_str = SPIDER_SQL_NULL_CHAR_STR, *last_str = SPIDER_SQL_NULL_CHAR_STR; @@ -3693,8 +3701,7 @@ int spider_db_mysql_util::open_item_func( if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); DBUG_RETURN(spider_db_open_item_int(item_func, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); + alias, alias_length, dbton_id, use_fields, fields)); } else if ( !strncasecmp("case", func_name, func_name_length) ) { @@ -3709,12 +3716,12 @@ int spider_db_mysql_util::open_item_func( if (item_func_case->first_expr_num != -1) { if ((error_num = spider_db_print_item_type( - item_list[item_func_case->first_expr_num], spider, str, + item_list[item_func_case->first_expr_num], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } - for (loop_count = 0; loop_count < item_func_case->ncases; - loop_count += 2) + for (roop_count = 0; roop_count < item_func_case->ncases; + roop_count += 2) { if (str) { @@ -3723,7 +3730,7 @@ int spider_db_mysql_util::open_item_func( str->q_append(SPIDER_SQL_WHEN_STR, SPIDER_SQL_WHEN_LEN); } if ((error_num = spider_db_print_item_type( - item_list[loop_count], spider, str, + item_list[roop_count], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -3733,7 +3740,7 @@ int spider_db_mysql_util::open_item_func( str->q_append(SPIDER_SQL_THEN_STR, SPIDER_SQL_THEN_LEN); } if ((error_num = spider_db_print_item_type( - item_list[loop_count + 1], spider, str, + item_list[roop_count + 1], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -3746,7 +3753,7 @@ int spider_db_mysql_util::open_item_func( str->q_append(SPIDER_SQL_ELSE_STR, SPIDER_SQL_ELSE_LEN); } if ((error_num = spider_db_print_item_type( - item_list[item_func_case->else_expr_num], spider, str, + item_list[item_func_case->else_expr_num], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -3784,9 +3791,7 @@ int spider_db_mysql_util::open_item_func( if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, - alias, alias_length, - dbton_id, - use_fields, fields)); + alias, alias_length, dbton_id, use_fields, fields)); } else if ( !strncasecmp("convert", func_name, func_name_length) ) { @@ -3811,8 +3816,7 @@ int spider_db_mysql_util::open_item_func( if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); + alias, alias_length, dbton_id, use_fields, fields)); } else if (func_name_length == 9 && !strncasecmp("isnottrue", func_name, func_name_length) ) { @@ -3928,9 +3932,7 @@ int spider_db_mysql_util::open_item_func( if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, - alias, alias_length, - dbton_id, - use_fields, fields)); + alias, alias_length, dbton_id, use_fields, fields)); } else if (!strncasecmp("timestampdiff", func_name, func_name_length)) { #ifdef ITEM_FUNC_TIMESTAMPDIFF_ARE_PUBLIC @@ -3992,7 +3994,7 @@ int spider_db_mysql_util::open_item_func( str->q_append(interval_str, interval_len); str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } - if ((error_num = spider_db_print_item_type(item_list[0], spider, + if ((error_num = spider_db_print_item_type(item_list[0], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -4001,7 +4003,7 @@ int spider_db_mysql_util::open_item_func( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } - if ((error_num = spider_db_print_item_type(item_list[1], spider, + if ((error_num = spider_db_print_item_type(item_list[1], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -4255,11 +4257,8 @@ int spider_db_mysql_util::open_item_func( func_name = spider_db_timefunc_interval_str[ item_date_add_interval->int_type]; func_name_length = strlen(func_name); - if ((error_num = spider_db_print_item_type(item_list[0], NULL, - spider, str, - alias, alias_length, - dbton_id, - use_fields, fields))) + if ((error_num = spider_db_print_item_type(item_list[0], NULL, spider, + str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) { @@ -4275,11 +4274,8 @@ int spider_db_mysql_util::open_item_func( str->q_append(SPIDER_SQL_INTERVAL_STR, SPIDER_SQL_INTERVAL_LEN); } } - if ((error_num = spider_db_print_item_type(item_list[1], NULL, - spider, str, - alias, alias_length, - dbton_id, - use_fields, fields))) + if ((error_num = spider_db_print_item_type(item_list[1], NULL, spider, + str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) { @@ -4309,9 +4305,8 @@ int spider_db_mysql_util::open_item_func( case Item_func::NOW_FUNC: if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, + str, alias, alias_length, dbton_id, use_fields, fields)); case Item_func::CHAR_TYPECAST_FUNC: DBUG_PRINT("info",("spider CHAR_TYPECAST_FUNC")); { @@ -4503,12 +4498,10 @@ int spider_db_mysql_util::open_item_func( str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (item_func->result_type() == STRING_RESULT) DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); + alias, alias_length, dbton_id, use_fields, fields)); else DBUG_RETURN(spider_db_open_item_int(item_func, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields)); + alias, alias_length, dbton_id, use_fields, fields)); case Item_func::FT_FUNC: if (spider_db_check_ft_idx(item_func, spider) == MAX_KEY) DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); @@ -4607,7 +4600,6 @@ int spider_db_mysql_util::open_item_func( DBUG_PRINT("info",("spider separator_str_length = %d", separator_str_length)); DBUG_PRINT("info",("spider last_str = %s", last_str)); DBUG_PRINT("info",("spider last_str_length = %d", last_str_length)); - if (item_count) { /* Find the field in the list of items of the expression tree */ @@ -4615,23 +4607,18 @@ int spider_db_mysql_util::open_item_func( item_count, start_item, str, func_name, func_name_length); - item_count--; - /* Loop through the items of the current function expression to print its portion of the statement */ - for (loop_count = start_item; loop_count < item_count; loop_count++) + for (roop_count = start_item; roop_count < item_count; roop_count++) { - item = item_list[loop_count]; + item = item_list[roop_count]; if ((error_num = spider_db_print_item_type(item, field, spider, str, - alias, alias_length, - dbton_id, - use_fields, fields))) + alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); - - if (loop_count == 1) + if (roop_count == 1) { /* Remaining operands need to be preceded by the separator */ func_name = separator_str; @@ -4648,11 +4635,9 @@ int spider_db_mysql_util::open_item_func( } /* Print the last operand value */ - item = item_list[loop_count]; + item = item_list[roop_count]; if ((error_num = spider_db_print_item_type(item, field, spider, str, - alias, alias_length, - dbton_id, - use_fields, fields))) + alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -4667,8 +4652,7 @@ int spider_db_mysql_util::open_item_func( } item = item_list[0]; if ((error_num = spider_db_print_item_type(item, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields))) + alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) { @@ -4755,11 +4739,8 @@ int spider_db_mysql_util::open_item_sum_func( for (roop_count = 0; roop_count < item_count; roop_count++) { item = args[roop_count]; - if ((error_num = spider_db_print_item_type(item, NULL, - spider, str, - alias, alias_length, - dbton_id, - use_fields, fields))) + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, + alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) { @@ -4770,9 +4751,7 @@ int spider_db_mysql_util::open_item_sum_func( } item = args[roop_count]; if ((error_num = spider_db_print_item_type(item, NULL, spider, str, - alias, alias_length, - dbton_id, - use_fields, fields))) + alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } if (str) @@ -4788,6 +4767,48 @@ int spider_db_mysql_util::open_item_sum_func( case Item_sum::SUM_DISTINCT_FUNC: case Item_sum::AVG_FUNC: case Item_sum::AVG_DISTINCT_FUNC: + { + if (!use_fields) + DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM); + const char *func_name = item_sum->func_name(); + uint func_name_length = strlen(func_name); + Item *item, **args = item_sum->get_args(); + if (str) + { + if (str->reserve(func_name_length)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(func_name, func_name_length); + } + if (item_count) + { + item_count--; + for (roop_count = 0; roop_count < item_count; roop_count++) + { + item = args[roop_count]; + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, + alias, alias_length, dbton_id, use_fields, fields))) + DBUG_RETURN(error_num); + if (str) + { + if (str->reserve(SPIDER_SQL_COMMA_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); + } + } + item = args[roop_count]; + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, + alias, alias_length, dbton_id, use_fields, fields))) + DBUG_RETURN(error_num); + } + if (str) + { + if (str->reserve(SPIDER_SQL_CLOSE_PAREN_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, + SPIDER_SQL_CLOSE_PAREN_LEN); + } + } + break; case Item_sum::STD_FUNC: case Item_sum::VARIANCE_FUNC: case Item_sum::SUM_BIT_FUNC: @@ -4813,59 +4834,529 @@ int spider_db_mysql_util::append_escaped_util( } #ifdef SPIDER_HAS_GROUP_BY_HANDLER -int spider_db_mysql_util::append_from_and_tables( +int spider_db_mysql_util::append_table( + ha_spider *spider, spider_fields *fields, - spider_string *str + spider_string *str, + TABLE_LIST *table_list, + TABLE_LIST **used_table_list, + uint *current_pos, + TABLE_LIST **cond_table_list_ptr, + bool top_down, + bool first ) { - SPIDER_TABLE_HOLDER *table_holder; int error_num; - uint dbton_id = spider_dbton_mysql.dbton_id, from_length; + bool use_cond_table_list = FALSE; spider_mysql_share *db_share; spider_mysql_handler *dbton_hdl; - ha_spider *spider; + SPIDER_TABLE_HOLDER *table_holder; + uint dbton_id = spider_dbton_mysql.dbton_id; + TABLE_LIST *cond_table_list = *cond_table_list_ptr; + ha_spider *spd; + DBUG_ENTER("spider_db_mysql_util::append_table"); + DBUG_PRINT("info",("spider table_list=%p", table_list)); + DBUG_PRINT("info",("spider table_list->outer_join=%u", + table_list->outer_join)); + DBUG_PRINT("info",("spider table_list->on_expr=%p", + table_list->on_expr)); + DBUG_PRINT("info",("spider table_list->join_using_fields=%p", + table_list->join_using_fields)); + DBUG_PRINT("info",("spider table_list->table=%p", + table_list->table)); + if (!top_down && table_list->embedding) + { + if ((error_num = append_embedding_tables(spider, fields, str, + table_list->embedding, used_table_list, current_pos, + cond_table_list_ptr))) + DBUG_RETURN(error_num); + } else if (!table_list->table) + { + if ((error_num = append_tables_top_down(spider, fields, str, table_list, + used_table_list, current_pos, cond_table_list_ptr))) + DBUG_RETURN(error_num); + } else { + if ( + table_list->outer_join || + table_list->on_expr || + table_list->join_using_fields + ) { + DBUG_PRINT("info",("spider use table_list")); + if (table_list->outer_join & JOIN_TYPE_LEFT) + { + if (str) + { + if (str->reserve(SPIDER_SQL_LEFT_JOIN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_LEFT_JOIN_STR, SPIDER_SQL_LEFT_JOIN_LEN); + } + } else { + if (str) + { + if (str->reserve(SPIDER_SQL_JOIN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_JOIN_STR, SPIDER_SQL_JOIN_LEN); + } + } + } else if ( + cond_table_list && + ( + cond_table_list->outer_join || + cond_table_list->on_expr || + cond_table_list->join_using_fields + ) + ) { + DBUG_PRINT("info",("spider use cond_table_list")); + if (cond_table_list->outer_join & (JOIN_TYPE_LEFT | JOIN_TYPE_RIGHT)) + { + if (str) + { + if (str->reserve(SPIDER_SQL_LEFT_JOIN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_LEFT_JOIN_STR, SPIDER_SQL_LEFT_JOIN_LEN); + } + } else { + if (str) + { + if (str->reserve(SPIDER_SQL_JOIN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_JOIN_STR, SPIDER_SQL_JOIN_LEN); + } + } + use_cond_table_list = TRUE; + } else if (*current_pos > 0 && !first) + { + DBUG_PRINT("info",("spider no condition")); + if (top_down) + { + if (str) + { + if (str->reserve(SPIDER_SQL_JOIN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_JOIN_STR, SPIDER_SQL_JOIN_LEN); + } + } else { + if (str) + { + if (str->reserve(SPIDER_SQL_COMMA_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); + } + } + } + + if (str) + { + table_holder = fields->get_table_holder(table_list->table); + spd = table_holder->spider; + db_share = (spider_mysql_share *) + spd->share->dbton_share[dbton_id]; + dbton_hdl = (spider_mysql_handler *) + spd->dbton_handler[dbton_id]; + + dbton_hdl->table_name_pos = str->length(); + + if (str->reserve( + db_share->db_nm_max_length + + SPIDER_SQL_DOT_LEN + /* SPIDER_SQL_NAME_QUOTE_LEN */ 4 + + db_share->table_nm_max_length + SPIDER_SQL_SPACE_LEN + + table_holder->alias->length() - SPIDER_SQL_DOT_LEN + )) { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + + if ((error_num = db_share->append_table_name_with_adjusting(str, + spd->conn_link_idx[dbton_hdl->first_link_idx]))) + { + DBUG_RETURN(error_num); + } + str->q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN); + str->q_append(table_holder->alias->ptr(), + table_holder->alias->length() - SPIDER_SQL_DOT_LEN); + } + used_table_list[(*current_pos)++] = table_list; + + if (str) + { + List *join_using_fields = table_list->join_using_fields; + if (!join_using_fields && cond_table_list) + { + join_using_fields = cond_table_list->join_using_fields; + } + + if (join_using_fields) + { + if (str->reserve(SPIDER_SQL_USING_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_USING_STR, SPIDER_SQL_USING_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, + SPIDER_SQL_OPEN_PAREN_LEN); + List_iterator_fast it2(*join_using_fields); + String *ptr; + while ((ptr = it2++)) + { + if (str->reserve(ptr->length() + SPIDER_SQL_COMMA_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(ptr->ptr(), ptr->length()); + str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); + } + str->length(str->length() - SPIDER_SQL_COMMA_LEN); + if (str->reserve(SPIDER_SQL_CLOSE_PAREN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, + SPIDER_SQL_CLOSE_PAREN_LEN); + } + } + + Item *on_expr = table_list->on_expr; + if (!on_expr && cond_table_list) + { + on_expr = cond_table_list->on_expr; + } + + if (on_expr) + { + if (str) + { + if (str->reserve(SPIDER_SQL_ON_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_ON_STR, SPIDER_SQL_ON_LEN); + } + if ((error_num = spider_db_print_item_type(on_expr, NULL, + spider, str, NULL, 0, dbton_id, TRUE, fields))) + { + DBUG_RETURN(error_num); + } + } + + if (use_cond_table_list) + { + (*cond_table_list_ptr) = NULL; + DBUG_PRINT("info",("spider cond_table_list=%p", (*cond_table_list_ptr))); + } + } + DBUG_RETURN(0); +} + +int spider_db_mysql_util::append_tables_top_down( + ha_spider *spider, + spider_fields *fields, + spider_string *str, + TABLE_LIST *table_list, + TABLE_LIST **used_table_list, + uint *current_pos, + TABLE_LIST **cond_table_list_ptr +) { + int error_num; + uint outer_join_backup; + TABLE_LIST *cur_table_list, *prev_table_list = NULL, *cond_table_list = NULL; + bool first; + DBUG_ENTER("spider_db_mysql_util::append_tables_top_down"); + DBUG_PRINT("info",("spider this=%p", this)); + if ( + table_list->outer_join || + table_list->on_expr || + table_list->join_using_fields + ) { + DBUG_ASSERT(!(*cond_table_list_ptr)); + (*cond_table_list_ptr) = table_list; + DBUG_PRINT("info",("spider cond_table_list=%p", table_list)); + } + List_iterator_fast it1(table_list->nested_join->join_list); + cur_table_list = it1++; + if (cur_table_list->outer_join & JOIN_TYPE_RIGHT) + { + first = FALSE; + prev_table_list = cur_table_list; + cur_table_list = it1++; + } else if (*cond_table_list_ptr) + { + first = TRUE; + cond_table_list = (*cond_table_list_ptr); + (*cond_table_list_ptr) = NULL; + if (cond_table_list->outer_join & JOIN_TYPE_LEFT) + { + if (str) + { + if (str->reserve(SPIDER_SQL_LEFT_JOIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_LEFT_JOIN_STR, SPIDER_SQL_LEFT_JOIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + } + } else { + if (str) + { + if (str->reserve(SPIDER_SQL_JOIN_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_JOIN_STR, SPIDER_SQL_JOIN_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); + } + } + } + + do { + if (cur_table_list->outer_join & JOIN_TYPE_RIGHT) + { + prev_table_list = cur_table_list; + } else { + if ((error_num = append_table(spider, fields, str, cur_table_list, + used_table_list, current_pos, cond_table_list_ptr, TRUE, first))) + DBUG_RETURN(error_num); + first = FALSE; + if (prev_table_list) + { + outer_join_backup = prev_table_list->outer_join; + prev_table_list->outer_join = JOIN_TYPE_LEFT; + if ((error_num = append_table(spider, fields, str, prev_table_list, + used_table_list, current_pos, cond_table_list_ptr, TRUE, FALSE))) + { + prev_table_list->outer_join = outer_join_backup; + DBUG_RETURN(error_num); + } + prev_table_list->outer_join = outer_join_backup; + prev_table_list = NULL; + } + } + } while ((cur_table_list = it1++)); + + if (cond_table_list) + { + if (str) + { + if (str->reserve(SPIDER_SQL_CLOSE_PAREN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, + SPIDER_SQL_CLOSE_PAREN_LEN); + + List *join_using_fields = cond_table_list->join_using_fields; + if (join_using_fields) + { + if (str->reserve(SPIDER_SQL_USING_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_USING_STR, SPIDER_SQL_USING_LEN); + str->q_append(SPIDER_SQL_OPEN_PAREN_STR, + SPIDER_SQL_OPEN_PAREN_LEN); + List_iterator_fast it2(*join_using_fields); + String *ptr; + while ((ptr = it2++)) + { + if (str->reserve(ptr->length() + SPIDER_SQL_COMMA_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(ptr->ptr(), ptr->length()); + str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); + } + str->length(str->length() - SPIDER_SQL_COMMA_LEN); + if (str->reserve(SPIDER_SQL_CLOSE_PAREN_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, + SPIDER_SQL_CLOSE_PAREN_LEN); + } + } + + Item *on_expr = cond_table_list->on_expr; + if (on_expr) + { + if (str) + { + if (str->reserve(SPIDER_SQL_ON_LEN)) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_ON_STR, SPIDER_SQL_ON_LEN); + } + if ((error_num = spider_db_print_item_type(on_expr, NULL, + spider, str, NULL, 0, spider_dbton_mysql.dbton_id, TRUE, fields))) + { + DBUG_RETURN(error_num); + } + } + } + DBUG_RETURN(0); +} + +int spider_db_mysql_util::append_tables_top_down_check( + TABLE_LIST *table_list, + TABLE_LIST **used_table_list, + uint *current_pos +) { + int error_num; + TABLE_LIST *cur_table_list; + DBUG_ENTER("spider_db_mysql_util::append_tables_top_down_check"); + DBUG_PRINT("info",("spider this=%p", this)); + List_iterator_fast it1(table_list->nested_join->join_list); + while ((cur_table_list = it1++)) + { + if (!cur_table_list->table) + { + if ((error_num = append_tables_top_down_check( + cur_table_list, used_table_list, current_pos))) + DBUG_RETURN(error_num); + } else { + used_table_list[(*current_pos)++] = cur_table_list; + } + } + DBUG_RETURN(0); +} + +int spider_db_mysql_util::append_embedding_tables( + ha_spider *spider, + spider_fields *fields, + spider_string *str, + TABLE_LIST *table_list, + TABLE_LIST **used_table_list, + uint *current_pos, + TABLE_LIST **cond_table_list_ptr +) { + int error_num; + TABLE_LIST *embedding = table_list->embedding; + DBUG_ENTER("spider_db_mysql_util::append_embedding_tables"); + DBUG_PRINT("info",("spider this=%p", this)); + if (embedding) + { + DBUG_PRINT("info",("spider embedding=%p", embedding)); + DBUG_PRINT("info",("spider embedding->outer_join=%u", + embedding->outer_join)); + DBUG_PRINT("info",("spider embedding->on_expr=%p", + embedding->on_expr)); + DBUG_PRINT("info",("spider embedding->join_using_fields=%p", + embedding->join_using_fields)); + DBUG_PRINT("info",("spider embedding->table=%p", + embedding->table)); + if ((error_num = append_embedding_tables(spider, fields, str, embedding, + used_table_list, current_pos, cond_table_list_ptr))) + DBUG_RETURN(error_num); + } else { + DBUG_PRINT("info",("spider table_list=%p", table_list)); + DBUG_PRINT("info",("spider table_list->outer_join=%u", + table_list->outer_join)); + DBUG_PRINT("info",("spider table_list->on_expr=%p", + table_list->on_expr)); + DBUG_PRINT("info",("spider table_list->join_using_fields=%p", + table_list->join_using_fields)); + DBUG_PRINT("info",("spider table_list->table=%p", + table_list->table)); + if (table_list->outer_join & JOIN_TYPE_RIGHT) + { + if ((error_num = append_tables_top_down_check(table_list, + used_table_list, current_pos))) + DBUG_RETURN(error_num); + DBUG_ASSERT(!(*cond_table_list_ptr)); + (*cond_table_list_ptr) = table_list; + DBUG_PRINT("info",("spider cond_table_list=%p", table_list)); + } else { + if ((error_num = append_tables_top_down(spider, fields, str, table_list, + used_table_list, current_pos, cond_table_list_ptr))) + DBUG_RETURN(error_num); + } + } + DBUG_RETURN(0); +} + +int spider_db_mysql_util::append_from_and_tables( + ha_spider *spider, + spider_fields *fields, + spider_string *str, + TABLE_LIST *table_list, + uint table_count +) { + int error_num; + uint current_pos = 0, roop_count, backup_pos, outer_join_backup; + TABLE *table; + TABLE_LIST **used_table_list, *prev_table_list = NULL, + *cond_table_list = NULL; DBUG_ENTER("spider_db_mysql_util::append_from_and_tables"); DBUG_PRINT("info",("spider this=%p", this)); + used_table_list = (TABLE_LIST **) + my_alloca(sizeof(TABLE_LIST *) * table_count); + if (!used_table_list) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); - /* calculate from size */ - from_length = SPIDER_SQL_FROM_LEN; - fields->set_pos_to_first_table_holder(); - while ((table_holder = fields->get_next_table_holder())) + if (str) { - spider = table_holder->spider; - db_share = (spider_mysql_share *) - spider->share->dbton_share[dbton_id]; - from_length += - db_share->db_nm_max_length + - SPIDER_SQL_DOT_LEN + /* SPIDER_SQL_NAME_QUOTE_LEN */ 4 + - db_share->table_nm_max_length + - SPIDER_SQL_SPACE_LEN + SPIDER_SQL_COMMA_LEN + - table_holder->alias->length() - SPIDER_SQL_DOT_LEN; + if (str->reserve(SPIDER_SQL_FROM_LEN)) + { + my_afree(used_table_list); + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + str->q_append(SPIDER_SQL_FROM_STR, SPIDER_SQL_FROM_LEN); } - if (str->reserve(from_length)) - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - str->q_append(SPIDER_SQL_FROM_STR, SPIDER_SQL_FROM_LEN); + do { + table = table_list->table; + if (table->const_table) + continue; - fields->set_pos_to_first_table_holder(); - while ((table_holder = fields->get_next_table_holder())) - { - spider = table_holder->spider; - db_share = (spider_mysql_share *) - spider->share->dbton_share[dbton_id]; - dbton_hdl = (spider_mysql_handler *) - spider->dbton_handler[dbton_id]; - dbton_hdl->table_name_pos = str->length(); - if ((error_num = db_share->append_table_name_with_adjusting(str, - spider->conn_link_idx[dbton_hdl->first_link_idx]))) + for (roop_count = 0; roop_count < current_pos; ++roop_count) { + if (used_table_list[roop_count] == table_list) + break; + } + if (roop_count < current_pos) + continue; + + if (prev_table_list) + current_pos = backup_pos; + else + backup_pos = current_pos; + if ((error_num = append_table(spider, fields, str, table_list, used_table_list, + ¤t_pos, &cond_table_list, FALSE, FALSE))) + { + my_afree(used_table_list); DBUG_RETURN(error_num); } - str->q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN); - str->q_append(table_holder->alias->ptr(), - table_holder->alias->length() - SPIDER_SQL_DOT_LEN); - str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); - } - str->length(str->length() - SPIDER_SQL_COMMA_LEN); + if (prev_table_list) + { + outer_join_backup = prev_table_list->outer_join; + prev_table_list->outer_join = JOIN_TYPE_LEFT; + if ((error_num = append_table(spider, fields, str, prev_table_list, + used_table_list, ¤t_pos, &cond_table_list, FALSE, FALSE))) + { + prev_table_list->outer_join = outer_join_backup; + my_afree(used_table_list); + DBUG_RETURN(error_num); + } + prev_table_list->outer_join = outer_join_backup; + prev_table_list = NULL; + } + if (cond_table_list && (cond_table_list->outer_join & JOIN_TYPE_RIGHT)) + { + prev_table_list = cond_table_list; + cond_table_list = NULL; + DBUG_PRINT("info",("spider cond_table_list=%p", cond_table_list)); + } + } while ((table_list = table_list->next_local)); + my_afree(used_table_list); DBUG_RETURN(0); } @@ -5344,7 +5835,7 @@ int spider_mysql_share::create_column_name_str() str->init_calc_mem(89); str->set_charset(spider_share->access_charset); if ((error_num = spider_db_append_name_with_quote_str(str, - (char *) (*field)->field_name.str, dbton_id))) + (*field)->field_name, dbton_id))) goto error; } DBUG_RETURN(0); @@ -5613,6 +6104,10 @@ int spider_mysql_share::append_table_select() spider_string *str = table_select; TABLE_SHARE *table_share = spider_share->table_share; DBUG_ENTER("spider_mysql_share::append_table_select"); + + if (!*table_share->field) + DBUG_RETURN(0); + for (field = table_share->field; *field; field++) { field_length = column_name_str[(*field)->field_index].length(); @@ -5637,6 +6132,10 @@ int spider_mysql_share::append_key_select( TABLE_SHARE *table_share = spider_share->table_share; const KEY *key_info = &table_share->key_info[idx]; DBUG_ENTER("spider_mysql_share::append_key_select"); + + if (!spider_user_defined_key_parts(key_info)) + DBUG_RETURN(0); + for (key_part = key_info->key_part, part_num = 0; part_num < spider_user_defined_key_parts(key_info); key_part++, part_num++) { @@ -7276,16 +7775,28 @@ int spider_mysql_handler::append_select( if (result_list->lock_type != F_WRLCK && spider->lock_mode < 1) { /* no lock */ +#ifdef SPIDER_SQL_CACHE_IS_IN_LEX + LEX *lex = spider->trx->thd->lex; +#else st_select_lex *select_lex = &spider->trx->thd->lex->select_lex; +#endif if ( +#ifdef SPIDER_SQL_CACHE_IS_IN_LEX + lex->sql_cache == LEX::SQL_CACHE && +#else select_lex->sql_cache == SELECT_LEX::SQL_CACHE && +#endif (spider->share->query_cache_sync & 1) ) { if (str->reserve(SPIDER_SQL_SQL_CACHE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_SQL_CACHE_STR, SPIDER_SQL_SQL_CACHE_LEN); } else if ( +#ifdef SPIDER_SQL_CACHE_IS_IN_LEX + lex->sql_cache == LEX::SQL_NO_CACHE && +#else select_lex->sql_cache == SELECT_LEX::SQL_NO_CACHE && +#endif (spider->share->query_cache_sync & 2) ) { if (str->reserve(SPIDER_SQL_SQL_NO_CACHE_LEN)) @@ -7652,8 +8163,7 @@ int spider_mysql_handler::check_item_type( DBUG_ENTER("spider_mysql_handler::check_item_type"); DBUG_PRINT("info",("spider this=%p", this)); error_num = spider_db_print_item_type(item, NULL, spider, NULL, NULL, 0, - spider_dbton_mysql.dbton_id, - FALSE, NULL); + spider_dbton_mysql.dbton_id, FALSE, NULL); DBUG_RETURN(error_num); } @@ -8276,22 +8786,67 @@ int spider_mysql_handler::append_update_where( ) { uint field_name_length; Field **field; + THD *thd = spider->trx->thd; SPIDER_SHARE *share = spider->share; + bool no_pk = (table->s->primary_key == MAX_KEY); DBUG_ENTER("spider_mysql_handler::append_update_where"); DBUG_PRINT("info", ("spider table->s->primary_key=%s", table->s->primary_key != MAX_KEY ? "TRUE" : "FALSE")); + uint str_len_bakup = str->length(); if (str->reserve(SPIDER_SQL_WHERE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_WHERE_STR, SPIDER_SQL_WHERE_LEN); - for (field = table->field; *field; field++) - { - DBUG_PRINT("info", ("spider bitmap=%s", - bitmap_is_set(table->read_set, (*field)->field_index) ? - "TRUE" : "FALSE")); - if ( - table->s->primary_key == MAX_KEY || - bitmap_is_set(table->read_set, (*field)->field_index) + + if ( + no_pk || + spider_param_use_cond_other_than_pk_for_update(thd) + ) { + for (field = table->field; *field; field++) + { + if ( + no_pk || + bitmap_is_set(table->read_set, (*field)->field_index) + ) { + field_name_length = + mysql_share->column_name_str[(*field)->field_index].length(); + if ((*field)->is_null(ptr_diff)) + { + if (str->reserve(field_name_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_IS_NULL_LEN + SPIDER_SQL_AND_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + mysql_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_IS_NULL_STR, SPIDER_SQL_IS_NULL_LEN); + } else { + if (str->reserve(field_name_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_EQUAL_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + mysql_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); + (*field)->move_field_offset(ptr_diff); + if ( + spider_db_mysql_utility. + append_column_value(spider, str, *field, NULL, + share->access_charset) || + str->reserve(SPIDER_SQL_AND_LEN) + ) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + (*field)->move_field_offset(-ptr_diff); + } + str->q_append(SPIDER_SQL_AND_STR, SPIDER_SQL_AND_LEN); + } + } + } else { + KEY *key_info = &table->key_info[table->s->primary_key]; + KEY_PART_INFO *key_part; + uint part_num; + for ( + key_part = key_info->key_part, part_num = 0; + part_num < spider_user_defined_key_parts(key_info); + key_part++, part_num++ ) { + field = &key_part->field; field_name_length = mysql_share->column_name_str[(*field)->field_index].length(); if ((*field)->is_null(ptr_diff)) @@ -8322,7 +8877,13 @@ int spider_mysql_handler::append_update_where( str->q_append(SPIDER_SQL_AND_STR, SPIDER_SQL_AND_LEN); } } - str->length(str->length() - SPIDER_SQL_AND_LEN); + if (str->length() == str_len_bakup + SPIDER_SQL_WHERE_LEN) + { + /* no condition */ + str->length(str_len_bakup); + } else { + str->length(str->length() - SPIDER_SQL_AND_LEN); + } if (str->reserve(SPIDER_SQL_LIMIT1_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_LIMIT1_STR, SPIDER_SQL_LIMIT1_LEN); @@ -8451,11 +9012,9 @@ int spider_mysql_handler::append_condition( str->q_append(SPIDER_SQL_AND_STR, SPIDER_SQL_AND_LEN); } } - if ((error_num = spider_db_print_item_type((Item *) tmp_cond->cond, - NULL, spider, str, - alias, alias_length, - spider_dbton_mysql.dbton_id, - FALSE, NULL))) + if ((error_num = spider_db_print_item_type( + (Item *) tmp_cond->cond, NULL, spider, str, alias, alias_length, + spider_dbton_mysql.dbton_id, FALSE, NULL))) { if (str && error_num == ER_SPIDER_COND_SKIP_NUM) { @@ -8778,9 +9337,7 @@ int spider_mysql_handler::append_group_by( for (; group; group = group->next) { if ((error_num = spider_db_print_item_type((*group->item), NULL, spider, - str, alias, alias_length, - spider_dbton_mysql.dbton_id, - FALSE, NULL))) + str, alias, alias_length, spider_dbton_mysql.dbton_id, FALSE, NULL))) { DBUG_RETURN(error_num); } @@ -8973,8 +9530,7 @@ int spider_mysql_handler::append_key_order_for_direct_order_limit_with_alias( { if ((error_num = spider_db_print_item_type((*order->item), NULL, spider, str, alias, - alias_length, spider_dbton_mysql.dbton_id, - FALSE, NULL))) + alias_length, spider_dbton_mysql.dbton_id, FALSE, NULL))) { DBUG_PRINT("info",("spider error=%d", error_num)); DBUG_RETURN(error_num); @@ -10602,8 +11158,14 @@ int spider_mysql_handler::mk_bulk_tmp_table_and_bulk_start() DBUG_PRINT("info",("spider this=%p", this)); if (!upd_tmp_tbl) { +#ifdef SPIDER_use_LEX_CSTRING_for_Field_blob_constructor + LEX_CSTRING field_name = {STRING_WITH_LEN("a")}; + if (!(upd_tmp_tbl = spider_mk_sys_tmp_table( + thd, table, &upd_tmp_tbl_prm, &field_name, update_sql.charset()))) +#else if (!(upd_tmp_tbl = spider_mk_sys_tmp_table( thd, table, &upd_tmp_tbl_prm, "a", update_sql.charset()))) +#endif { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } @@ -11295,8 +11857,7 @@ int spider_mysql_handler::show_table_status( conn->mta_conn_mutex_unlock_later = FALSE; if (error_num || (error_num = spider_db_errorno(conn))) DBUG_RETURN(error_num); - else - { + else { my_printf_error(ER_SPIDER_REMOTE_TABLE_NOT_FOUND_NUM, ER_SPIDER_REMOTE_TABLE_NOT_FOUND_STR, MYF(0), mysql_share->db_names_str[spider->conn_link_idx[link_idx]].ptr(), @@ -11496,7 +12057,6 @@ int spider_mysql_handler::show_table_status( DBUG_PRINT("info",("spider auto_increment_value=%llu", share->lgtm_tblhnd_share->auto_increment_value)); } - DBUG_RETURN(0); } @@ -12740,6 +13300,8 @@ int spider_mysql_handler::append_from_and_tables_part( ) { int error_num; spider_string *str; + SPIDER_TABLE_HOLDER *table_holder; + TABLE_LIST *table_list; DBUG_ENTER("spider_mysql_handler::append_from_and_tables_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) @@ -12750,7 +13312,12 @@ int spider_mysql_handler::append_from_and_tables_part( default: DBUG_RETURN(0); } - error_num = spider_db_mysql_utility.append_from_and_tables(fields, str); + fields->set_pos_to_first_table_holder(); + table_holder = fields->get_next_table_holder(); + table_list = table_holder->table->pos_in_table_list; + error_num = spider_db_mysql_utility.append_from_and_tables( + table_holder->spider, fields, str, + table_list, fields->get_table_count()); DBUG_RETURN(error_num); } @@ -12834,9 +13401,7 @@ int spider_mysql_handler::append_item_type_part( DBUG_RETURN(0); } error_num = spider_db_print_item_type(item, NULL, spider, str, - alias, alias_length, - spider_dbton_mysql.dbton_id, - use_fields, fields); + alias, alias_length, spider_dbton_mysql.dbton_id, use_fields, fields); DBUG_RETURN(error_num); } @@ -12884,21 +13449,18 @@ int spider_mysql_handler::append_list_item_select( while ((item = it++)) { if ((error_num = spider_db_print_item_type(item, NULL, spider, str, - alias, alias_length, dbton_id, - use_fields, fields))) + alias, alias_length, dbton_id, use_fields, fields))) { DBUG_RETURN(error_num); } field = *(fields->get_next_field_ptr()); if (field) { - item_name = field->field_name.str; - length = field->field_name.length; - } - else - { - item_name = item->name.str; - length = item->name.length; + item_name = SPIDER_field_name_str(field); + length = SPIDER_field_name_length(field); + } else { + item_name = SPIDER_item_name_str(item); + length = SPIDER_item_name_length(item); } if (str->reserve( SPIDER_SQL_COMMA_LEN + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + @@ -12907,7 +13469,7 @@ int spider_mysql_handler::append_list_item_select( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN); if ((error_num = spider_db_mysql_utility.append_name(str, - item_name, length))) + item_name, length))) { DBUG_RETURN(error_num); } @@ -12962,9 +13524,7 @@ int spider_mysql_handler::append_group_by( for (; order; order = order->next) { if ((error_num = spider_db_print_item_type((*order->item), NULL, spider, - str, alias, alias_length, - dbton_id, - use_fields, fields))) + str, alias, alias_length, dbton_id, use_fields, fields))) { DBUG_RETURN(error_num); } @@ -13022,9 +13582,7 @@ int spider_mysql_handler::append_order_by( for (; order; order = order->next) { if ((error_num = spider_db_print_item_type((*order->item), NULL, spider, - str, alias, alias_length, - dbton_id, - use_fields, fields))) + str, alias, alias_length, dbton_id, use_fields, fields))) { DBUG_RETURN(error_num); } @@ -13147,7 +13705,7 @@ int spider_mysql_copy_table::append_table_columns( DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - (char *) (*field)->field_name.str, spider_dbton_mysql.dbton_id))) + (*field)->field_name, spider_dbton_mysql.dbton_id))) DBUG_RETURN(error_num); if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN + SPIDER_SQL_COMMA_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -13276,7 +13834,7 @@ int spider_mysql_copy_table::append_key_order_str( DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - (char *) field->field_name.str, spider_dbton_mysql.dbton_id))) + field->field_name, spider_dbton_mysql.dbton_id))) DBUG_RETURN(error_num); if (key_part->key_part_flag & HA_REVERSE_SORT) { @@ -13306,7 +13864,7 @@ int spider_mysql_copy_table::append_key_order_str( DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - (char *) field->field_name.str, spider_dbton_mysql.dbton_id))) + field->field_name, spider_dbton_mysql.dbton_id))) DBUG_RETURN(error_num); if (key_part->key_part_flag & HA_REVERSE_SORT) { @@ -13438,7 +13996,7 @@ int spider_mysql_copy_table::copy_key_row( DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - (char *) field->field_name.str, spider_dbton_mysql.dbton_id))) + field->field_name, spider_dbton_mysql.dbton_id))) DBUG_RETURN(error_num); if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN + joint_length + *length + SPIDER_SQL_AND_LEN)) diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index 25cad01c66c..423ead89423 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2017 Kentoku Shiba +/* Copyright (C) 2012-2018 Kentoku Shiba 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 @@ -13,8 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "tztime.h" - class spider_db_mysql_util: public spider_db_util { public: @@ -121,9 +119,46 @@ public: String *from ); #ifdef SPIDER_HAS_GROUP_BY_HANDLER - int append_from_and_tables( + int append_table( + ha_spider *spider, spider_fields *fields, - spider_string *str + spider_string *str, + TABLE_LIST *table_list, + TABLE_LIST **used_table_list, + uint *current_pos, + TABLE_LIST **cond_table_list_ptr, + bool top_down, + bool first + ); + int append_tables_top_down( + ha_spider *spider, + spider_fields *fields, + spider_string *str, + TABLE_LIST *table_list, + TABLE_LIST **used_table_list, + uint *current_pos, + TABLE_LIST **cond_table_list_ptr + ); + int append_tables_top_down_check( + TABLE_LIST *table_list, + TABLE_LIST **used_table_list, + uint *current_pos + ); + int append_embedding_tables( + ha_spider *spider, + spider_fields *fields, + spider_string *str, + TABLE_LIST *table_list, + TABLE_LIST **used_table_list, + uint *current_pos, + TABLE_LIST **cond_table_list_ptr + ); + int append_from_and_tables( + ha_spider *spider, + spider_fields *fields, + spider_string *str, + TABLE_LIST *table_list, + uint table_count ); int reappend_tables( spider_fields *fields, diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc index b852a43282c..dfeafc58f13 100644 --- a/storage/spider/spd_db_oracle.cc +++ b/storage/spider/spd_db_oracle.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2017 Kentoku Shiba +/* Copyright (C) 2012-2018 Kentoku Shiba 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 @@ -152,6 +152,9 @@ static const int spider_db_table_lock_len[] = sizeof(" in exclusive mode") - 1 }; +/* UTC time zone for timestamp columns */ +extern Time_zone *UTC; + int spider_db_oracle_get_error( sword res, dvoid *hndlp, @@ -2410,8 +2413,13 @@ void spider_db_oracle::set_dup_key_idx( key_name = spider->share->tgt_pk_names[all_link_idx]; key_name_length = spider->share->tgt_pk_names_lengths[all_link_idx]; } else { +#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name + key_name = (char *) table->s->key_info[roop_count].name.str; + key_name_length = table->s->key_info[roop_count].name.length; +#else key_name = table->s->key_info[roop_count].name; key_name_length = strlen(key_name); +#endif } memcpy(tmp_pos, key_name, key_name_length + 1); DBUG_PRINT("info",("spider key_name=%s", key_name)); @@ -2529,9 +2537,12 @@ int spider_db_oracle_util::append_column_value( spider_string tmp_str(buf, MAX_FIELD_WIDTH, &my_charset_bin); String *ptr; uint length; + Time_zone *saved_time_zone = thd->variables.time_zone; DBUG_ENTER("spider_db_oracle_util::append_column_value"); tmp_str.init_calc_mem(181); + thd->variables.time_zone = UTC; + if (new_ptr) { if ( @@ -2625,6 +2636,9 @@ int spider_db_oracle_util::append_column_value( ptr = field->val_str(tmp_str.get_str()); tmp_str.mem_calc(); } + + thd->variables.time_zone = saved_time_zone; + DBUG_PRINT("info", ("spider field->type() is %d", field->type())); DBUG_PRINT("info", ("spider ptr->length() is %d", ptr->length())); /* @@ -2909,12 +2923,13 @@ int spider_db_oracle_util::open_item_func( uint dbton_id = spider_dbton_oracle.dbton_id; int error_num; Item *item, **item_list = item_func->arguments(); + Field *field; uint roop_count, item_count = item_func->argument_count(), start_item = 0; const char *func_name = SPIDER_SQL_NULL_CHAR_STR, - *separete_str = SPIDER_SQL_NULL_CHAR_STR, + *separator_str = SPIDER_SQL_NULL_CHAR_STR, *last_str = SPIDER_SQL_NULL_CHAR_STR; int func_name_length = SPIDER_SQL_NULL_CHAR_LEN, - separete_str_length = SPIDER_SQL_NULL_CHAR_LEN, + separator_str_length = SPIDER_SQL_NULL_CHAR_LEN, last_str_length = SPIDER_SQL_NULL_CHAR_LEN; int use_pushdown_udf; bool merge_func = FALSE; @@ -2980,7 +2995,7 @@ int spider_db_oracle_util::open_item_func( ) { if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_int(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_int(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); } else if ( !strncasecmp("case", func_name, func_name_length) @@ -2996,7 +3011,7 @@ int spider_db_oracle_util::open_item_func( if (item_func_case->first_expr_num != -1) { if ((error_num = spider_db_print_item_type( - item_list[item_func_case->first_expr_num], spider, str, + item_list[item_func_case->first_expr_num], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -3010,7 +3025,7 @@ int spider_db_oracle_util::open_item_func( str->q_append(SPIDER_SQL_WHEN_STR, SPIDER_SQL_WHEN_LEN); } if ((error_num = spider_db_print_item_type( - item_list[roop_count], spider, str, + item_list[roop_count], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -3020,7 +3035,7 @@ int spider_db_oracle_util::open_item_func( str->q_append(SPIDER_SQL_THEN_STR, SPIDER_SQL_THEN_LEN); } if ((error_num = spider_db_print_item_type( - item_list[roop_count + 1], spider, str, + item_list[roop_count + 1], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -3033,7 +3048,7 @@ int spider_db_oracle_util::open_item_func( str->q_append(SPIDER_SQL_ELSE_STR, SPIDER_SQL_ELSE_LEN); } if ((error_num = spider_db_print_item_type( - item_list[item_func_case->else_expr_num], spider, str, + item_list[item_func_case->else_expr_num], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -3070,7 +3085,7 @@ int spider_db_oracle_util::open_item_func( ) { if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_string(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); } else if ( !strncasecmp("convert", func_name, func_name_length) @@ -3095,7 +3110,7 @@ int spider_db_oracle_util::open_item_func( ) { if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_string(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); } else if (func_name_length == 9 && !strncasecmp("isnottrue", func_name, func_name_length) @@ -3122,8 +3137,8 @@ int spider_db_oracle_util::open_item_func( } func_name = SPIDER_SQL_COMMA_STR; func_name_length = SPIDER_SQL_COMMA_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; break; } } else if (func_name_length == 12) @@ -3211,7 +3226,7 @@ int spider_db_oracle_util::open_item_func( { if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_string(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); } else if (!strncasecmp("timestampdiff", func_name, func_name_length)) { @@ -3274,7 +3289,7 @@ int spider_db_oracle_util::open_item_func( str->q_append(interval_str, interval_len); str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } - if ((error_num = spider_db_print_item_type(item_list[0], spider, + if ((error_num = spider_db_print_item_type(item_list[0], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -3283,7 +3298,7 @@ int spider_db_oracle_util::open_item_func( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } - if ((error_num = spider_db_print_item_type(item_list[1], spider, + if ((error_num = spider_db_print_item_type(item_list[1], NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -3549,8 +3564,9 @@ int spider_db_oracle_util::open_item_func( str->q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN); } - if ((error_num = spider_db_print_item_type(item_list[0], spider, - str, alias, alias_length, dbton_id, use_fields, fields))) + if ((error_num = spider_db_print_item_type(item_list[0], NULL, + spider, str, alias, alias_length, dbton_id, use_fields, + fields))) DBUG_RETURN(error_num); if (str) { @@ -3567,8 +3583,9 @@ int spider_db_oracle_util::open_item_func( str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } } - if ((error_num = spider_db_print_item_type(item_list[1], spider, - str, alias, alias_length, dbton_id, use_fields, fields))) + if ((error_num = spider_db_print_item_type(item_list[1], NULL, + spider, str, alias, alias_length, dbton_id, use_fields, + fields))) DBUG_RETURN(error_num); if (str) { @@ -3613,8 +3630,9 @@ int spider_db_oracle_util::open_item_func( case INTERVAL_MINUTE: case INTERVAL_SECOND: case INTERVAL_MICROSECOND: - if ((error_num = spider_db_print_item_type(item_list[0], spider, - str, alias, alias_length, dbton_id, use_fields, fields))) + if ((error_num = spider_db_print_item_type(item_list[0], NULL, + spider, str, alias, alias_length, dbton_id, use_fields, + fields))) DBUG_RETURN(error_num); if (str) { @@ -3629,8 +3647,9 @@ int spider_db_oracle_util::open_item_func( str->q_append(SPIDER_SQL_PLUS_STR, SPIDER_SQL_PLUS_LEN); } } - if ((error_num = spider_db_print_item_type(item_list[1], spider, - str, alias, alias_length, dbton_id, use_fields, fields))) + if ((error_num = spider_db_print_item_type(item_list[1], NULL, + spider, str, alias, alias_length, dbton_id, use_fields, + fields))) DBUG_RETURN(error_num); if (str) { @@ -3709,15 +3728,15 @@ int spider_db_oracle_util::open_item_func( } func_name = SPIDER_SQL_COMMA_STR; func_name_length = SPIDER_SQL_COMMA_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; case Item_func::NOW_FUNC: if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); - DBUG_RETURN(spider_db_open_item_string(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); case Item_func::CHAR_TYPECAST_FUNC: DBUG_PRINT("info",("spider CHAR_TYPECAST_FUNC")); @@ -3843,15 +3862,15 @@ int spider_db_oracle_util::open_item_func( { func_name = SPIDER_SQL_NOT_IN_STR; func_name_length = SPIDER_SQL_NOT_IN_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; } else { func_name = SPIDER_SQL_IN_STR; func_name_length = SPIDER_SQL_IN_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; } @@ -3861,13 +3880,13 @@ int spider_db_oracle_util::open_item_func( { func_name = SPIDER_SQL_NOT_BETWEEN_STR; func_name_length = SPIDER_SQL_NOT_BETWEEN_LEN; - separete_str = SPIDER_SQL_AND_STR; - separete_str_length = SPIDER_SQL_AND_LEN; + separator_str = SPIDER_SQL_AND_STR; + separator_str_length = SPIDER_SQL_AND_LEN; } else { func_name = (char*) item_func->func_name(); func_name_length = strlen(func_name); - separete_str = SPIDER_SQL_AND_STR; - separete_str_length = SPIDER_SQL_AND_LEN; + separator_str = SPIDER_SQL_AND_STR; + separator_str_length = SPIDER_SQL_AND_LEN; } break; case Item_func::UDF_FUNC: @@ -3888,8 +3907,8 @@ int spider_db_oracle_util::open_item_func( } func_name = SPIDER_SQL_COMMA_STR; func_name_length = SPIDER_SQL_COMMA_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; @@ -3909,10 +3928,10 @@ int spider_db_oracle_util::open_item_func( if (str) str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN); if (item_func->result_type() == STRING_RESULT) - DBUG_RETURN(spider_db_open_item_string(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_string(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); else - DBUG_RETURN(spider_db_open_item_int(item_func, spider, str, + DBUG_RETURN(spider_db_open_item_int(item_func, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields)); case Item_func::FT_FUNC: if (spider_db_check_ft_idx(item_func, spider) == MAX_KEY) @@ -3924,8 +3943,8 @@ int spider_db_oracle_util::open_item_func( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_MATCH_STR, SPIDER_SQL_MATCH_LEN); } - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; @@ -3942,8 +3961,8 @@ int spider_db_oracle_util::open_item_func( } func_name = SPIDER_SQL_COMMA_STR; func_name_length = SPIDER_SQL_COMMA_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; @@ -3974,8 +3993,8 @@ int spider_db_oracle_util::open_item_func( } func_name = SPIDER_SQL_COMMA_STR; func_name_length = SPIDER_SQL_COMMA_LEN; - separete_str = SPIDER_SQL_COMMA_STR; - separete_str_length = SPIDER_SQL_COMMA_LEN; + separator_str = SPIDER_SQL_COMMA_STR; + separator_str_length = SPIDER_SQL_COMMA_LEN; last_str = SPIDER_SQL_CLOSE_PAREN_STR; last_str_length = SPIDER_SQL_CLOSE_PAREN_LEN; break; @@ -4008,23 +4027,28 @@ int spider_db_oracle_util::open_item_func( } DBUG_PRINT("info",("spider func_name = %s", func_name)); DBUG_PRINT("info",("spider func_name_length = %d", func_name_length)); - DBUG_PRINT("info",("spider separete_str = %s", separete_str)); - DBUG_PRINT("info",("spider separete_str_length = %d", separete_str_length)); + DBUG_PRINT("info",("spider separator_str = %s", separator_str)); + DBUG_PRINT("info",("spider separator_str_length = %d", separator_str_length)); DBUG_PRINT("info",("spider last_str = %s", last_str)); DBUG_PRINT("info",("spider last_str_length = %d", last_str_length)); if (item_count) { + /* Find the field in the list of items of the expression tree */ + field = spider_db_find_field_in_item_list(item_list, + item_count, start_item, + str, + func_name, func_name_length); item_count--; for (roop_count = start_item; roop_count < item_count; roop_count++) { item = item_list[roop_count]; - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, field, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (roop_count == 1) { - func_name = separete_str; - func_name_length = separete_str_length; + func_name = separator_str; + func_name_length = separator_str_length; } if (str) { @@ -4036,7 +4060,7 @@ int spider_db_oracle_util::open_item_func( } } item = item_list[roop_count]; - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, field, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -4050,7 +4074,7 @@ int spider_db_oracle_util::open_item_func( str->q_append(SPIDER_SQL_AGAINST_STR, SPIDER_SQL_AGAINST_LEN); } item = item_list[0]; - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -4138,7 +4162,7 @@ int spider_db_oracle_util::open_item_sum_func( for (roop_count = 0; roop_count < item_count; roop_count++) { item = args[roop_count]; - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); if (str) @@ -4149,7 +4173,7 @@ int spider_db_oracle_util::open_item_sum_func( } } item = args[roop_count]; - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) DBUG_RETURN(error_num); } @@ -4209,8 +4233,11 @@ int spider_db_oracle_util::append_escaped_util( #ifdef SPIDER_HAS_GROUP_BY_HANDLER int spider_db_oracle_util::append_from_and_tables( + ha_spider *spider, spider_fields *fields, - spider_string *str + spider_string *str, + TABLE_LIST *table_list, + uint table_count ) { SPIDER_TABLE_HOLDER *table_holder; int error_num; @@ -4745,7 +4772,7 @@ int spider_oracle_share::create_column_name_str() str->init_calc_mem(196); str->set_charset(spider_share->access_charset); if ((error_num = spider_db_append_name_with_quote_str(str, - (char *) (*field)->field_name.str, dbton_id))) + (*field)->field_name, dbton_id))) goto error; } DBUG_RETURN(0); @@ -5188,6 +5215,10 @@ int spider_oracle_share::append_table_select() spider_string *str = table_select; TABLE_SHARE *table_share = spider_share->table_share; DBUG_ENTER("spider_oracle_share::append_table_select"); + + if (!*table_share->field) + DBUG_RETURN(0); + for (field = table_share->field; *field; field++) { field_length = column_name_str[(*field)->field_index].length(); @@ -5212,6 +5243,10 @@ int spider_oracle_share::append_key_select( TABLE_SHARE *table_share = spider_share->table_share; const KEY *key_info = &table_share->key_info[idx]; DBUG_ENTER("spider_oracle_share::append_key_select"); + + if (!spider_user_defined_key_parts(key_info)) + DBUG_RETURN(0); + for (key_part = key_info->key_part, part_num = 0; part_num < spider_user_defined_key_parts(key_info); key_part++, part_num++) { @@ -6414,7 +6449,7 @@ int spider_oracle_handler::append_update_columns( { value = vi++; if ((error_num = spider_db_print_item_type( - (Item *) field, spider, str, alias, alias_length, + (Item *) field, NULL, spider, str, alias, alias_length, spider_dbton_oracle.dbton_id, FALSE, NULL))) { if ( @@ -6432,8 +6467,8 @@ int spider_oracle_handler::append_update_columns( str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); } if ((error_num = spider_db_print_item_type( - (Item *) value, spider, str, alias, alias_length, - spider_dbton_oracle.dbton_id, FALSE, NULL))) + (Item *) value, ((Item_field *) field)->field, spider, str, + alias, alias_length, spider_dbton_oracle.dbton_id, FALSE, NULL))) DBUG_RETURN(error_num); if (str) { @@ -6834,7 +6869,7 @@ int spider_oracle_handler::check_item_type( int error_num; DBUG_ENTER("spider_oracle_handler::check_item_type"); DBUG_PRINT("info",("spider this=%p", this)); - error_num = spider_db_print_item_type(item, spider, NULL, NULL, 0, + error_num = spider_db_print_item_type(item, NULL, spider, NULL, NULL, 0, spider_dbton_oracle.dbton_id, FALSE, NULL); DBUG_RETURN(error_num); } @@ -7437,17 +7472,64 @@ int spider_oracle_handler::append_update_where( ) { uint field_name_length; Field **field; + THD *thd = spider->trx->thd; SPIDER_SHARE *share = spider->share; + bool no_pk = (table->s->primary_key == MAX_KEY); DBUG_ENTER("spider_oracle_handler::append_update_where"); + uint str_len_bakup = str->length(); if (str->reserve(SPIDER_SQL_WHERE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_WHERE_STR, SPIDER_SQL_WHERE_LEN); - for (field = table->field; *field; field++) - { - if ( - table->s->primary_key == MAX_KEY || - bitmap_is_set(table->read_set, (*field)->field_index) + if ( + no_pk || + spider_param_use_cond_other_than_pk_for_update(thd) + ) { + for (field = table->field; *field; field++) + { + if ( + no_pk || + bitmap_is_set(table->read_set, (*field)->field_index) + ) { + field_name_length = + oracle_share->column_name_str[(*field)->field_index].length(); + if ((*field)->is_null(ptr_diff)) + { + if (str->reserve(field_name_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_IS_NULL_LEN + SPIDER_SQL_AND_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + oracle_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_IS_NULL_STR, SPIDER_SQL_IS_NULL_LEN); + } else { + if (str->reserve(field_name_length + + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + + SPIDER_SQL_EQUAL_LEN)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + oracle_share->append_column_name(str, (*field)->field_index); + str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); + (*field)->move_field_offset(ptr_diff); + if ( + spider_db_oracle_utility. + append_column_value(spider, str, *field, NULL, + share->access_charset) || + str->reserve(SPIDER_SQL_AND_LEN) + ) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + (*field)->move_field_offset(-ptr_diff); + } + str->q_append(SPIDER_SQL_AND_STR, SPIDER_SQL_AND_LEN); + } + } + } else { + KEY *key_info = &table->key_info[table->s->primary_key]; + KEY_PART_INFO *key_part; + uint part_num; + for ( + key_part = key_info->key_part, part_num = 0; + part_num < spider_user_defined_key_parts(key_info); + key_part++, part_num++ ) { + field = &key_part->field; field_name_length = oracle_share->column_name_str[(*field)->field_index].length(); if ((*field)->is_null(ptr_diff)) @@ -7478,9 +7560,13 @@ int spider_oracle_handler::append_update_where( str->q_append(SPIDER_SQL_AND_STR, SPIDER_SQL_AND_LEN); } } -/* - str->length(str->length() - SPIDER_SQL_AND_LEN); -*/ + if (str->length() == str_len_bakup + SPIDER_SQL_WHERE_LEN) + { + /* no condition */ + str->length(str_len_bakup); + } else { + str->length(str->length() - SPIDER_SQL_AND_LEN); + } if (str->reserve(SPIDER_SQL_LIMIT1_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_LIMIT1_STR, SPIDER_SQL_LIMIT1_LEN); @@ -7615,7 +7701,7 @@ int spider_oracle_handler::append_condition( } } if ((error_num = spider_db_print_item_type( - (Item *) tmp_cond->cond, spider, str, alias, alias_length, + (Item *) tmp_cond->cond, NULL, spider, str, alias, alias_length, spider_dbton_oracle.dbton_id, FALSE, NULL))) { if (str && error_num == ER_SPIDER_COND_SKIP_NUM) @@ -7937,8 +8023,8 @@ int spider_oracle_handler::append_group_by( str->q_append(SPIDER_SQL_GROUP_STR, SPIDER_SQL_GROUP_LEN); for (; group; group = group->next) { - if ((error_num = spider_db_print_item_type((*group->item), spider, str, - alias, alias_length, spider_dbton_oracle.dbton_id, FALSE, NULL))) + if ((error_num = spider_db_print_item_type((*group->item), NULL, spider, + str, alias, alias_length, spider_dbton_oracle.dbton_id, FALSE, NULL))) { DBUG_RETURN(error_num); } @@ -8276,8 +8362,8 @@ int spider_oracle_handler::append_key_order_for_direct_order_limit_with_alias( order = order->next) { if ((error_num = - spider_db_print_item_type((*order->item), spider, &sql_part, alias, - alias_length, spider_dbton_oracle.dbton_id, FALSE, NULL))) + spider_db_print_item_type((*order->item), NULL, spider, &sql_part, + alias, alias_length, spider_dbton_oracle.dbton_id, FALSE, NULL))) { DBUG_PRINT("info",("spider error=%d", error_num)); DBUG_RETURN(error_num); @@ -8367,7 +8453,7 @@ int spider_oracle_handler::append_key_order_for_direct_order_limit_with_alias( order = order->next) { if ((error_num = - spider_db_print_item_type((*order->item), spider, str, alias, + spider_db_print_item_type((*order->item), NULL, spider, str, alias, alias_length, spider_dbton_oracle.dbton_id, FALSE, NULL))) { DBUG_PRINT("info",("spider error=%d", error_num)); @@ -10199,8 +10285,14 @@ int spider_oracle_handler::mk_bulk_tmp_table_and_bulk_start() DBUG_PRINT("info",("spider this=%p", this)); if (!upd_tmp_tbl) { +#ifdef SPIDER_use_LEX_CSTRING_for_Field_blob_constructor + LEX_CSTRING field_name = {STRING_WITH_LEN("a")}; + if (!(upd_tmp_tbl = spider_mk_sys_tmp_table( + thd, table, &upd_tmp_tbl_prm, &field_name, update_sql.charset()))) +#else if (!(upd_tmp_tbl = spider_mk_sys_tmp_table( thd, table, &upd_tmp_tbl_prm, "a", update_sql.charset()))) +#endif { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } @@ -12454,6 +12546,8 @@ int spider_oracle_handler::append_from_and_tables_part( ) { int error_num; spider_string *str; + SPIDER_TABLE_HOLDER *table_holder; + TABLE_LIST *table_list; DBUG_ENTER("spider_oracle_handler::append_from_and_tables_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) @@ -12464,7 +12558,11 @@ int spider_oracle_handler::append_from_and_tables_part( default: DBUG_RETURN(0); } - error_num = spider_db_oracle_utility.append_from_and_tables(fields, str); + fields->set_pos_to_first_table_holder(); + table_holder = fields->get_next_table_holder(); + table_list = table_holder->table->pos_in_table_list; + error_num = spider_db_oracle_utility.append_from_and_tables(fields, str, + table_list); DBUG_RETURN(error_num); } @@ -12547,8 +12645,8 @@ int spider_oracle_handler::append_item_type_part( default: DBUG_RETURN(0); } - error_num = spider_db_print_item_type(item, spider, str, alias, alias_length, - spider_dbton_oracle.dbton_id, use_fields, fields); + error_num = spider_db_print_item_type(item, NULL, spider, str, + alias, alias_length, spider_dbton_oracle.dbton_id, use_fields, fields); DBUG_RETURN(error_num); } @@ -12589,18 +12687,26 @@ int spider_oracle_handler::append_list_item_select( uint dbton_id = spider_dbton_oracle.dbton_id, length; List_iterator_fast it(*select); Item *item; - Field **field_ptr; + Field *field; + const char *item_name; DBUG_ENTER("spider_oracle_handler::append_list_item_select"); DBUG_PRINT("info",("spider this=%p", this)); while ((item = it++)) { - if ((error_num = spider_db_print_item_type(item, spider, str, + if ((error_num = spider_db_print_item_type(item, NULL, spider, str, alias, alias_length, dbton_id, use_fields, fields))) { DBUG_RETURN(error_num); } - field_ptr = fields->get_next_field_ptr(); - length = strlen((*field_ptr)->field_name); + field = *(fields->get_next_field_ptr()); + if (field) + { + item_name = SPIDER_field_name_str(field); + length = SPIDER_field_name_length(field); + } else { + item_name = SPIDER_item_name_str(item); + length = SPIDER_item_name_length(item); + } if (str->reserve( SPIDER_SQL_COMMA_LEN + /* SPIDER_SQL_NAME_QUOTE_LEN */ 2 + SPIDER_SQL_SPACE_LEN + length @@ -12608,7 +12714,7 @@ int spider_oracle_handler::append_list_item_select( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN); if ((error_num = spider_db_oracle_utility.append_name(str, - (*field_ptr)->field_name, length))) + item_name, length))) { DBUG_RETURN(error_num); } @@ -12662,8 +12768,8 @@ int spider_oracle_handler::append_group_by( str->q_append(SPIDER_SQL_GROUP_STR, SPIDER_SQL_GROUP_LEN); for (; order; order = order->next) { - if ((error_num = spider_db_print_item_type((*order->item), spider, str, - alias, alias_length, dbton_id, use_fields, fields))) + if ((error_num = spider_db_print_item_type((*order->item), NULL, spider, + str, alias, alias_length, dbton_id, use_fields, fields))) { DBUG_RETURN(error_num); } @@ -12720,8 +12826,8 @@ int spider_oracle_handler::append_order_by( str->q_append(SPIDER_SQL_ORDER_STR, SPIDER_SQL_ORDER_LEN); for (; order; order = order->next) { - if ((error_num = spider_db_print_item_type((*order->item), spider, str, - alias, alias_length, dbton_id, use_fields, fields))) + if ((error_num = spider_db_print_item_type((*order->item), NULL, spider, + str, alias, alias_length, dbton_id, use_fields, fields))) { DBUG_RETURN(error_num); } @@ -12831,7 +12937,7 @@ int spider_oracle_copy_table::append_table_columns( DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - (char *) (*field)->field_name.str, spider_dbton_oracle.dbton_id))) + (*field)->field_name, spider_dbton_oracle.dbton_id))) DBUG_RETURN(error_num); if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN + SPIDER_SQL_COMMA_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -12977,7 +13083,7 @@ int spider_oracle_copy_table::append_key_order_str( sql_part.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql_part, - (char *) field->field_name.str, spider_dbton_oracle.dbton_id))) + field->field_name, spider_dbton_oracle.dbton_id))) DBUG_RETURN(error_num); if (key_part->key_part_flag & HA_REVERSE_SORT) { @@ -13011,7 +13117,7 @@ int spider_oracle_copy_table::append_key_order_str( sql_part.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql_part, - (char *) field->field_name.str, spider_dbton_oracle.dbton_id))) + field->field_name, spider_dbton_oracle.dbton_id))) DBUG_RETURN(error_num); if (key_part->key_part_flag & HA_REVERSE_SORT) { @@ -13075,7 +13181,7 @@ int spider_oracle_copy_table::append_key_order_str( sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - (char *) field->field_name.str, spider_dbton_oracle.dbton_id))) + field->field_name, spider_dbton_oracle.dbton_id))) DBUG_RETURN(error_num); if (key_part->key_part_flag & HA_REVERSE_SORT) { @@ -13108,7 +13214,7 @@ int spider_oracle_copy_table::append_key_order_str( sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - (char *) field->field_name.str, spider_dbton_oracle.dbton_id))) + field->field_name, spider_dbton_oracle.dbton_id))) DBUG_RETURN(error_num); if (key_part->key_part_flag & HA_REVERSE_SORT) { @@ -13316,7 +13422,7 @@ int spider_oracle_copy_table::copy_key_row( DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - (char *) field->field_name.str, spider_dbton_oracle.dbton_id))) + field->field_name, spider_dbton_oracle.dbton_id))) DBUG_RETURN(error_num); if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN + joint_length + *length + SPIDER_SQL_AND_LEN)) diff --git a/storage/spider/spd_db_oracle.h b/storage/spider/spd_db_oracle.h index 6962ff4884f..9f9c75f0090 100644 --- a/storage/spider/spd_db_oracle.h +++ b/storage/spider/spd_db_oracle.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2017 Kentoku Shiba +/* Copyright (C) 2012-2018 Kentoku Shiba 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 @@ -13,8 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "tztime.h" - class spider_db_oracle; class spider_db_oracle_result; @@ -131,8 +129,11 @@ public: ); #ifdef SPIDER_HAS_GROUP_BY_HANDLER int append_from_and_tables( + ha_spider *spider, spider_fields *fields, - spider_string *str + spider_string *str, + TABLE_LIST *table_list, + uint table_count ); int reappend_tables( spider_fields *fields, diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index d56848f5dbd..65d5142e1f1 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2017 Kentoku Shiba +/* Copyright (C) 2009-2018 Kentoku Shiba 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 @@ -27,6 +27,7 @@ #include "sql_partition.h" #include "sql_base.h" #include "sql_servers.h" +#include "tztime.h" #endif #include "spd_err.h" #include "spd_param.h" @@ -65,6 +66,9 @@ extern pthread_mutex_t spider_conn_id_mutex; extern pthread_mutex_t spider_ipport_conn_mutex; extern ulonglong spider_conn_id; +/* UTC time zone for timestamp columns */ +extern Time_zone *UTC; + uint spider_udf_calc_hash( char *key, uint mod @@ -132,7 +136,7 @@ int spider_udf_direct_sql_create_table_list( &direct_sql->tables, sizeof(TABLE*) * table_count, &tmp_name_ptr, sizeof(char) * ( table_name_list_length + - thd->db.length * table_count + + SPIDER_THD_db_length(thd) * table_count + 2 * table_count ), &direct_sql->iop, sizeof(int) * table_count, @@ -163,11 +167,11 @@ int spider_udf_direct_sql_create_table_list( tmp_name_ptr += length + 1; tmp_ptr = tmp_ptr3 + 1; } else { - if (thd->db.str) + if (SPIDER_THD_db_str(thd)) { - memcpy(tmp_name_ptr, thd->db.str, - thd->db.length + 1); - tmp_name_ptr += thd->db.length + 1; + memcpy(tmp_name_ptr, SPIDER_THD_db_str(thd), + SPIDER_THD_db_length(thd) + 1); + tmp_name_ptr += SPIDER_THD_db_length(thd) + 1; } else { direct_sql->db_names[roop_count] = (char *) ""; } @@ -395,6 +399,13 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( int *need_mon; DBUG_ENTER("spider_udf_direct_sql_create_conn"); + if (unlikely(!UTC)) + { + /* UTC time zone for timestamp columns */ + String tz_00_name(STRING_WITH_LEN("+00:00"), &my_charset_bin); + UTC = my_tz_find(current_thd, &tz_00_name); + } + #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) if (direct_sql->access_mode == 0) { @@ -976,8 +987,7 @@ error: start_ptr, TRUE, ¶m_string_parse))) \ direct_sql->SPIDER_PARAM_STR_LEN(param_name) = \ strlen(direct_sql->param_name); \ - else \ - { \ + else { \ error_num = param_string_parse.print_param_error(); \ goto error; \ } \ @@ -1330,10 +1340,10 @@ int spider_udf_set_direct_sql_param_default( if (!direct_sql->tgt_default_db_name) { DBUG_PRINT("info",("spider create default tgt_default_db_name")); - direct_sql->tgt_default_db_name_length = trx->thd->db.length; + direct_sql->tgt_default_db_name_length = SPIDER_THD_db_length(trx->thd); if ( !(direct_sql->tgt_default_db_name = spider_create_string( - trx->thd->db.str, + SPIDER_THD_db_str(trx->thd), direct_sql->tgt_default_db_name_length)) ) { my_error(ER_OUT_OF_RESOURCES, MYF(0), HA_ERR_OUT_OF_MEM); @@ -1686,14 +1696,29 @@ long long spider_direct_sql_body( for (roop_count = 0; roop_count < direct_sql->table_count; roop_count++) { #ifdef SPIDER_NEED_INIT_ONE_TABLE_FOR_FIND_TEMPORARY_TABLE - LEX_CSTRING db_name= { direct_sql->db_names[roop_count], - strlen(direct_sql->db_names[roop_count]) }; - LEX_CSTRING tbl_name= { direct_sql->table_names[roop_count], - strlen(direct_sql->table_names[roop_count]) }; +#ifdef SPIDER_use_LEX_CSTRING_for_database_tablename_alias + LEX_CSTRING db_name = + { + direct_sql->db_names[roop_count], + strlen(direct_sql->db_names[roop_count]) + }; + LEX_CSTRING tbl_name = + { + direct_sql->table_names[roop_count], + strlen(direct_sql->table_names[roop_count]) + }; table_list.init_one_table(&db_name, &tbl_name, 0, TL_WRITE); #else - table_list.db = direct_sql->db_names[roop_count]; - table_list.table_name = direct_sql->table_names[roop_count]; + table_list.init_one_table(direct_sql->db_names[roop_count], + strlen(direct_sql->db_names[roop_count]), + direct_sql->table_names[roop_count], + strlen(direct_sql->table_names[roop_count]), + direct_sql->table_names[roop_count], TL_WRITE); +#endif +#else + SPIDER_TABLE_LIST_db_str(&table_list) = direct_sql->db_names[roop_count]; + SPIDER_TABLE_LIST_table_name_str(&table_list) = + direct_sql->table_names[roop_count]; #endif if (!(direct_sql->tables[roop_count] = SPIDER_find_temporary_table(thd, &table_list))) @@ -1706,16 +1731,28 @@ long long spider_direct_sql_body( error_num = ER_SPIDER_UDF_TMP_TABLE_NOT_FOUND_NUM; my_printf_error(ER_SPIDER_UDF_TMP_TABLE_NOT_FOUND_NUM, ER_SPIDER_UDF_TMP_TABLE_NOT_FOUND_STR, - MYF(0), table_list.db.str, table_list.table_name.str); + MYF(0), SPIDER_TABLE_LIST_db_str(&table_list), + SPIDER_TABLE_LIST_table_name_str(&table_list)); goto error; #if MYSQL_VERSION_ID < 50500 #else } TABLE_LIST *tables = &direct_sql->table_list[roop_count]; - - table_list.init_one_table(&table_list.db, &table_list.table_name, 0, TL_WRITE); - tables->mdl_request.init(MDL_key::TABLE, table_list.db.str, - table_list.table_name.str, MDL_SHARED_WRITE, MDL_TRANSACTION); +#ifdef SPIDER_use_LEX_CSTRING_for_database_tablename_alias + table_list.init_one_table( + &table_list.db, &table_list.table_name, 0, TL_WRITE); +#else + tables->init_one_table( + SPIDER_TABLE_LIST_db_str(&table_list), + SPIDER_TABLE_LIST_db_length(&table_list), + SPIDER_TABLE_LIST_table_name_str(&table_list), + SPIDER_TABLE_LIST_table_name_length(&table_list), + SPIDER_TABLE_LIST_table_name_str(&table_list), TL_WRITE); +#endif + tables->mdl_request.init(MDL_key::TABLE, + SPIDER_TABLE_LIST_db_str(&table_list), + SPIDER_TABLE_LIST_table_name_str(&table_list), + MDL_SHARED_WRITE, MDL_TRANSACTION); if (!direct_sql->table_list_first) { direct_sql->table_list_first = tables; diff --git a/storage/spider/spd_environ.h b/storage/spider/spd_environ.h index ef7e6ff88c8..5e66a912582 100644 --- a/storage/spider/spd_environ.h +++ b/storage/spider/spd_environ.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba & 2017 MariaDB corp +/* Copyright (C) 2008-2018 Kentoku Shiba & 2017 MariaDB corp 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 @@ -37,4 +37,17 @@ #define HANDLER_HAS_NEED_INFO_FOR_AUTO_INC #define HANDLER_HAS_CAN_USE_FOR_AUTO_INC_INIT #endif + +#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100300 +#define SPIDER_UPDATE_ROW_HAS_CONST_NEW_DATA +#endif + +#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100309 +#define SPIDER_MDEV_16246 +#endif + +#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100400 +#define SPIDER_USE_CONST_ITEM_FOR_STRING_INT_REAL_DECIMAL_DATE_ITEM +#define SPIDER_SQL_CACHE_IS_IN_LEX +#endif #endif /* SPD_ENVIRON_INCLUDED */ diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index 0f8479b6ca6..86a9f8cba68 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -172,6 +172,7 @@ int spider_fields::make_link_idx_chain( add_link_idx_holder->table_link_idx_holder = dup_link_idx_holder->table_link_idx_holder; add_link_idx_holder->link_idx = dup_link_idx_holder->link_idx; + add_link_idx_holder->link_status = dup_link_idx_holder->link_status; link_idx_holder->next = add_link_idx_holder; } link_idx_holder = link_idx_holder->next; @@ -446,6 +447,8 @@ bool spider_fields::check_link_ok_chain( for (current_link_idx_chain = first_link_idx_chain; current_link_idx_chain; current_link_idx_chain = current_link_idx_chain->next) { + DBUG_PRINT("info",("spider current_link_idx_chain=%p", current_link_idx_chain)); + DBUG_PRINT("info",("spider current_link_idx_chain->link_status=%d", current_link_idx_chain->link_status)); if (current_link_idx_chain->link_status == SPIDER_LINK_STATUS_OK) { first_ok_link_idx_chain = current_link_idx_chain; @@ -924,8 +927,8 @@ SPIDER_TABLE_HOLDER *spider_fields::add_table( bool spider_fields::all_query_fields_are_query_table_members() { SPIDER_FIELD_HOLDER *field_holder; - DBUG_ENTER("spider_fields::all_fields_are_query_table_fields"); - DBUG_PRINT("info", ("spider this=%p", this)); + DBUG_ENTER("spider_fields::all_query_fields_are_query_table_members"); + DBUG_PRINT("info",("spider this=%p", this)); set_pos_to_first_field_holder(); while ((field_holder = get_next_field_holder())) @@ -977,6 +980,25 @@ SPIDER_TABLE_HOLDER *spider_fields::get_next_table_holder( DBUG_RETURN(return_table_holder); } +SPIDER_TABLE_HOLDER *spider_fields::get_table_holder(TABLE *table) +{ + uint table_num; + DBUG_ENTER("spider_fields::get_table_holder"); + DBUG_PRINT("info",("spider this=%p", this)); + for (table_num = 0; table_num < table_count; ++table_num) + { + if (table_holder[table_num].table == table) + DBUG_RETURN(&table_holder[table_num]); + } + DBUG_RETURN(NULL); +} + +uint spider_fields::get_table_count() +{ + DBUG_ENTER("spider_fields::get_table_count"); + DBUG_RETURN(table_count); +} + int spider_fields::add_field( Field *field_arg ) { @@ -1191,7 +1213,8 @@ int spider_group_by_handler::init_scan() *field; field++ ) { - DBUG_PRINT("info",("spider field_name=%s", (*field)->field_name.str)); + DBUG_PRINT("info",("spider field_name=%s", + SPIDER_field_name_str(*field))); } #endif @@ -1757,7 +1780,7 @@ group_by_handler *spider_create_group_by_handler( { DBUG_PRINT("info",("spider select item=%p", item)); if (spider_db_print_item_type(item, NULL, spider, NULL, NULL, 0, - roop_count, TRUE, fields_arg)) + roop_count, TRUE, fields_arg)) { DBUG_PRINT("info",("spider dbton_id=%d can't create select", roop_count)); spider_clear_bit(dbton_bitmap, roop_count); @@ -1766,13 +1789,22 @@ group_by_handler *spider_create_group_by_handler( } } if (keep_going) + { + if (spider_dbton[roop_count].db_util->append_from_and_tables( + spider, fields_arg, NULL, query->from, table_idx)) + { + DBUG_PRINT("info",("spider dbton_id=%d can't create from", roop_count)); + spider_clear_bit(dbton_bitmap, roop_count); + keep_going = FALSE; + } + } + if (keep_going) { DBUG_PRINT("info",("spider query->where=%p", query->where)); if (query->where) { - if (spider_db_print_item_type(query->where, NULL, spider, NULL, - NULL, 0, roop_count, - TRUE, fields_arg)) + if (spider_db_print_item_type(query->where, NULL, spider, NULL, NULL, 0, + roop_count, TRUE, fields_arg)) { DBUG_PRINT("info",("spider dbton_id=%d can't create where", roop_count)); spider_clear_bit(dbton_bitmap, roop_count); @@ -1787,9 +1819,8 @@ group_by_handler *spider_create_group_by_handler( { for (order = query->group_by; order; order = order->next) { - if (spider_db_print_item_type((*order->item), NULL, spider, NULL, - NULL, 0, roop_count, - TRUE, fields_arg)) + if (spider_db_print_item_type((*order->item), NULL, spider, NULL, NULL, 0, + roop_count, TRUE, fields_arg)) { DBUG_PRINT("info",("spider dbton_id=%d can't create group by", roop_count)); spider_clear_bit(dbton_bitmap, roop_count); @@ -1806,9 +1837,8 @@ group_by_handler *spider_create_group_by_handler( { for (order = query->order_by; order; order = order->next) { - if (spider_db_print_item_type((*order->item), NULL, spider, NULL, - NULL, 0, roop_count, - TRUE, fields_arg)) + if (spider_db_print_item_type((*order->item), NULL, spider, NULL, NULL, 0, + roop_count, TRUE, fields_arg)) { DBUG_PRINT("info",("spider dbton_id=%d can't create order by", roop_count)); spider_clear_bit(dbton_bitmap, roop_count); @@ -1823,9 +1853,8 @@ group_by_handler *spider_create_group_by_handler( DBUG_PRINT("info",("spider query->having=%p", query->having)); if (query->having) { - if (spider_db_print_item_type(query->having, NULL, spider, NULL, - NULL, 0, roop_count, - TRUE, fields_arg)) + if (spider_db_print_item_type(query->having, NULL, spider, NULL, NULL, 0, + roop_count, TRUE, fields_arg)) { DBUG_PRINT("info",("spider dbton_id=%d can't create having", roop_count)); spider_clear_bit(dbton_bitmap, roop_count); diff --git a/storage/spider/spd_i_s.cc b/storage/spider/spd_i_s.cc index 8a7ad752bcd..9c9e066b62f 100644 --- a/storage/spider/spd_i_s.cc +++ b/storage/spider/spd_i_s.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2012-2017 Kentoku Shiba +/* Copyright (C) 2012-2018 Kentoku Shiba 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 @@ -164,6 +164,6 @@ struct st_maria_plugin spider_i_s_alloc_mem_maria = NULL, NULL, "1.0", - MariaDB_PLUGIN_MATURITY_STABLE + MariaDB_PLUGIN_MATURITY_STABLE, }; #endif diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 79e030b0872..38ded445d44 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -13,9 +13,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "tztime.h" - -#define SPIDER_DETAIL_VERSION "3.3.13" +#define SPIDER_DETAIL_VERSION "3.3.14" #define SPIDER_HEX_VERSION 0x0303 #if MYSQL_VERSION_ID < 50500 @@ -76,12 +74,21 @@ #define spider_user_defined_key_parts(A) (A)->user_defined_key_parts #define spider_join_table_count(A) (A)->table_count #define SPIDER_CAN_BG_UPDATE (1LL << 39) -#define SPIDER_ALTER_PARTITION_ADD ALTER_PARTITION_ADD -#define SPIDER_ALTER_PARTITION_DROP ALTER_PARTITION_DROP -#define SPIDER_ALTER_PARTITION_COALESCE ALTER_PARTITION_COALESCE -#define SPIDER_ALTER_PARTITION_REORGANIZE ALTER_PARTITION_REORGANIZE -#define SPIDER_ALTER_PARTITION_TABLE_REORG ALTER_PARTITION_TABLE_REORG -#define SPIDER_ALTER_PARTITION_REBUILD ALTER_PARTITION_REBUILD +#if MYSQL_VERSION_ID >= 100304 +#define SPIDER_ALTER_PARTITION_ADD ALTER_PARTITION_ADD +#define SPIDER_ALTER_PARTITION_DROP ALTER_PARTITION_DROP +#define SPIDER_ALTER_PARTITION_COALESCE ALTER_PARTITION_COALESCE +#define SPIDER_ALTER_PARTITION_REORGANIZE ALTER_PARTITION_REORGANIZE +#define SPIDER_ALTER_PARTITION_TABLE_REORG ALTER_PARTITION_TABLE_REORG +#define SPIDER_ALTER_PARTITION_REBUILD ALTER_PARTITION_REBUILD +#else +#define SPIDER_ALTER_PARTITION_ADD Alter_info::ALTER_ADD_PARTITION +#define SPIDER_ALTER_PARTITION_DROP Alter_info::ALTER_DROP_PARTITION +#define SPIDER_ALTER_PARTITION_COALESCE Alter_info::ALTER_COALESCE_PARTITION +#define SPIDER_ALTER_PARTITION_REORGANIZE Alter_info::ALTER_REORGANIZE_PARTITION +#define SPIDER_ALTER_PARTITION_TABLE_REORG Alter_info::ALTER_TABLE_REORG +#define SPIDER_ALTER_PARTITION_REBUILD Alter_info::ALTER_REBUILD_PARTITION +#endif #define SPIDER_WARN_LEVEL_WARN Sql_condition::WARN_LEVEL_WARN #define SPIDER_WARN_LEVEL_NOTE Sql_condition::WARN_LEVEL_NOTE #define SPIDER_THD_KILL_CONNECTION KILL_CONNECTION @@ -100,12 +107,12 @@ #endif #define spider_user_defined_key_parts(A) (A)->key_parts #define spider_join_table_count(A) (A)->tables -#define SPIDER_ALTER_PARTITION_ADD ALTER_PARTITION_ADD -#define SPIDER_ALTER_PARTITION_DROP ALTER_PARTITION_DROP -#define SPIDER_ALTER_PARTITION_COALESCE ALTER_PARTITION_COALESCE -#define SPIDER_ALTER_PARTITION_REORGANIZE ALTER_PARTITION_REORGANIZE -#define SPIDER_ALTER_PARTITION_TABLE_REORG ALTER_PARTITION_TABLE_REORG -#define SPIDER_ALTER_PARTITION_REBUILD ALTER_PARTITION_REBUILD +#define SPIDER_ALTER_PARTITION_ADD ALTER_ADD_PARTITION +#define SPIDER_ALTER_PARTITION_DROP ALTER_DROP_PARTITION +#define SPIDER_ALTER_PARTITION_COALESCE ALTER_COALESCE_PARTITION +#define SPIDER_ALTER_PARTITION_REORGANIZE ALTER_REORGANIZE_PARTITION +#define SPIDER_ALTER_PARTITION_TABLE_REORG ALTER_TABLE_REORG +#define SPIDER_ALTER_PARTITION_REBUILD ALTER_REBUILD_PARTITION #define SPIDER_WARN_LEVEL_WARN MYSQL_ERROR::WARN_LEVEL_WARN #define SPIDER_WARN_LEVEL_NOTE MYSQL_ERROR::WARN_LEVEL_NOTE #define SPIDER_THD_KILL_CONNECTION THD::KILL_CONNECTION @@ -182,10 +189,56 @@ #define SPIDER_free_part_syntax(A,B) spider_my_free(A,B) #endif +#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100306 +#define SPIDER_read_record_read_record(A) read_record() +#define SPIDER_has_Item_with_subquery +#define SPIDER_use_LEX_CSTRING_for_KEY_Field_name +#define SPIDER_use_LEX_CSTRING_for_Field_blob_constructor +#define SPIDER_use_LEX_CSTRING_for_database_tablename_alias +#define SPIDER_THD_db_str(A) (A)->db.str +#define SPIDER_THD_db_length(A) (A)->db.length +#define SPIDER_TABLE_LIST_db_str(A) (A)->db.str +#define SPIDER_TABLE_LIST_db_length(A) (A)->db.length +#define SPIDER_TABLE_LIST_table_name_str(A) (A)->table_name.str +#define SPIDER_TABLE_LIST_table_name_length(A) (A)->table_name.length +#define SPIDER_TABLE_LIST_alias_str(A) (A)->alias.str +#define SPIDER_TABLE_LIST_alias_length(A) (A)->alias.length +#define SPIDER_field_name_str(A) (A)->field_name.str +#define SPIDER_field_name_length(A) (A)->field_name.length +#define SPIDER_item_name_str(A) (A)->name.str +#define SPIDER_item_name_length(A) (A)->name.length +const LEX_CSTRING SPIDER_empty_string = {"", 0}; +#else +#define SPIDER_read_record_read_record(A) read_record(A) +#define SPIDER_THD_db_str(A) (A)->db +#define SPIDER_THD_db_length(A) (A)->db_length +#define SPIDER_TABLE_LIST_db_str(A) (A)->db +#define SPIDER_TABLE_LIST_db_length(A) (A)->db_length +#define SPIDER_TABLE_LIST_table_name_str(A) (A)->table_name +#define SPIDER_TABLE_LIST_table_name_length(A) (A)->table_name_length +#define SPIDER_TABLE_LIST_alias_str(A) (A)->alias +#define SPIDER_TABLE_LIST_alias_length(A) strlen((A)->alias) +#define SPIDER_field_name_str(A) (A)->field_name +#define SPIDER_field_name_length(A) strlen((A)->field_name) +#define SPIDER_item_name_str(A) (A)->name +#define SPIDER_item_name_length(A) strlen((A)->name) +const char SPIDER_empty_string = ""; +#endif + #if MYSQL_VERSION_ID >= 50500 #define SPIDER_HAS_HASH_VALUE_TYPE #endif +#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100400 +#define SPIDER_date_mode_t(A) date_mode_t(A) +#define SPIDER_str_to_datetime(A,B,C,D,E) str_to_datetime_or_date(A,B,C,D,E) +#define SPIDER_get_linkage(A) A->get_linkage() +#else +#define SPIDER_date_mode_t(A) A +#define SPIDER_str_to_datetime(A,B,C,D,E) str_to_datetime(A,B,C,D,E) +#define SPIDER_get_linkage(A) A->linkage +#endif + #define spider_bitmap_size(A) ((A + 7) / 8) #define spider_set_bit(BITMAP, BIT) \ ((BITMAP)[(BIT) / 8] |= (1 << ((BIT) & 7))) diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc index 9c7aa4dcdcb..a90f628603e 100644 --- a/storage/spider/spd_param.cc +++ b/storage/spider/spd_param.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -3123,6 +3123,30 @@ int spider_param_bka_table_name_type( bka_table_name_type : THDVAR(thd, bka_table_name_type)); } +/* + -1 :use table parameter + 0 :off + 1 :on + */ +static MYSQL_THDVAR_INT( + use_cond_other_than_pk_for_update, /* name */ + PLUGIN_VAR_RQCMDARG, /* opt */ + "Use all conditions even if condition has pk", /* comment */ + NULL, /* check */ + NULL, /* update */ + 1, /* def */ + 0, /* min */ + 1, /* max */ + 0 /* blk */ +); + +int spider_param_use_cond_other_than_pk_for_update( + THD *thd +) { + DBUG_ENTER("spider_param_reset_sql_alloc"); + DBUG_RETURN(THDVAR(thd, use_cond_other_than_pk_for_update)); +} + static int spider_store_last_sts; /* -1 : use table parameter @@ -3421,6 +3445,7 @@ static struct st_mysql_sys_var* spider_system_variables[] = { MYSQL_SYSVAR(dry_access), MYSQL_SYSVAR(delete_all_rows_type), MYSQL_SYSVAR(bka_table_name_type), + MYSQL_SYSVAR(use_cond_other_than_pk_for_update), MYSQL_SYSVAR(connect_error_interval), #ifndef WITHOUT_SPIDER_BG_SEARCH MYSQL_SYSVAR(table_sts_thread_count), diff --git a/storage/spider/spd_param.h b/storage/spider/spd_param.h index 06df06a3129..e615fc672d4 100644 --- a/storage/spider/spd_param.h +++ b/storage/spider/spd_param.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -397,6 +397,9 @@ int spider_param_bka_table_name_type( THD *thd, int bka_table_name_type ); +int spider_param_use_cond_other_than_pk_for_update( + THD *thd +); int spider_param_store_last_sts( int store_last_sts ); diff --git a/storage/spider/spd_ping_table.cc b/storage/spider/spd_ping_table.cc index 680618e3087..f72487f034c 100644 --- a/storage/spider/spd_ping_table.cc +++ b/storage/spider/spd_ping_table.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2017 Kentoku Shiba +/* Copyright (C) 2009-2018 Kentoku Shiba 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 diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index ed25e4fcf32..14f80b41108 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -38,7 +38,6 @@ extern handlerton *spider_hton_ptr; extern Time_zone *spd_tz_system; -static const LEX_CSTRING empty_clex_string= {"", 0}; /** Insert a Spider system table row. @@ -155,15 +154,30 @@ TABLE *spider_open_sys_table( #if MYSQL_VERSION_ID < 50500 memset(&tables, 0, sizeof(TABLE_LIST)); - tables.db = (char*)"mysql"; - tables.db_length = sizeof("mysql") - 1; - tables.alias = tables.table_name = (char *) table_name; - tables.table_name_length = table_name_length; + SPIDER_TABLE_LIST_db_str(&tables) = (char*)"mysql"; + SPIDER_TABLE_LIST_db_length(&tables) = sizeof("mysql") - 1; + SPIDER_TABLE_LIST_alias_str(&tables) = + SPIDER_TABLE_LIST_table_name_str(&tables) = (char *) table_name; + SPIDER_TABLE_LIST_table_name_length(&tables) = table_name_length; tables.lock_type = (write ? TL_WRITE : TL_READ); #else - LEX_CSTRING db_name= { "mysql", sizeof("mysql") - 1 }; - LEX_CSTRING tbl_name= { table_name, (size_t) table_name_length }; - tables.init_one_table( &db_name, &tbl_name, 0, (write ? TL_WRITE : TL_READ)); +#ifdef SPIDER_use_LEX_CSTRING_for_database_tablename_alias + LEX_CSTRING db_name = + { + "mysql", + sizeof("mysql") - 1 + }; + LEX_CSTRING tbl_name = + { + table_name, + (size_t) table_name_length + }; + tables.init_one_table(&db_name, &tbl_name, 0, (write ? TL_WRITE : TL_READ)); +#else + tables.init_one_table( + "mysql", sizeof("mysql") - 1, table_name, table_name_length, table_name, + (write ? TL_WRITE : TL_READ)); +#endif #endif #if MYSQL_VERSION_ID < 50500 @@ -371,14 +385,15 @@ TABLE *spider_sys_open_table( TABLE *table; ulonglong utime_after_lock_backup = thd->utime_after_lock; DBUG_ENTER("spider_sys_open_table"); - thd->reset_n_backup_open_tables_state(open_tables_backup); + if (open_tables_backup) + thd->reset_n_backup_open_tables_state(open_tables_backup); if ((table = open_ltable(thd, tables, tables->lock_type, MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK | MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY | MYSQL_OPEN_IGNORE_FLUSH | MYSQL_LOCK_IGNORE_TIMEOUT | MYSQL_LOCK_LOG_TABLE ))) { table->use_all_columns(); table->s->no_replicate = 1; - } else + } else if (open_tables_backup) thd->restore_backup_open_tables_state(open_tables_backup); thd->utime_after_lock = utime_after_lock_backup; DBUG_RETURN(table); @@ -504,7 +519,7 @@ int spider_get_sys_table_by_idx( ) { int error_num; uint key_length; - KEY *key_info = table->key_info; + KEY *key_info = table->key_info + idx; DBUG_ENTER("spider_get_sys_table_by_idx"); if ((error_num = spider_sys_index_init(table, idx, FALSE))) DBUG_RETURN(error_num); @@ -595,6 +610,28 @@ int spider_sys_index_first( DBUG_RETURN(0); } +int spider_sys_index_last( + TABLE *table, + const int idx +) { + int error_num; + DBUG_ENTER("spider_sys_index_last"); + if ((error_num = spider_sys_index_init(table, idx, FALSE))) + DBUG_RETURN(error_num); + + if ( +#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50200 + (error_num = table->file->ha_index_last(table->record[0])) +#else + (error_num = table->file->index_last(table->record[0])) +#endif + ) { + spider_sys_index_end(table); + DBUG_RETURN(error_num); + } + DBUG_RETURN(0); +} + int spider_sys_index_next( TABLE *table ) { @@ -1262,7 +1299,9 @@ int spider_insert_xa( spider_store_xa_bqual_length(table, xid); spider_store_xa_status(table, status); if ((error_num = spider_write_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } else { my_message(ER_SPIDER_XA_EXISTS_NUM, ER_SPIDER_XA_EXISTS_STR, MYF(0)); DBUG_RETURN(ER_SPIDER_XA_EXISTS_NUM); @@ -1293,7 +1332,9 @@ int spider_insert_xa_member( table->use_all_columns(); spider_store_xa_member_info(table, xid, conn); if ((error_num = spider_write_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } else { my_message(ER_SPIDER_XA_MEMBER_EXISTS_NUM, ER_SPIDER_XA_MEMBER_EXISTS_STR, MYF(0)); @@ -1324,7 +1365,9 @@ int spider_insert_tables( share->alter_table.tmp_link_statuses[roop_count] : SPIDER_LINK_STATUS_OK); if ((error_num = spider_write_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } DBUG_RETURN(0); @@ -1335,9 +1378,8 @@ int spider_insert_sys_table( ) { int error_num; DBUG_ENTER("spider_insert_sys_table"); - if ((error_num = spider_write_sys_table_row(table))) - DBUG_RETURN(error_num); - DBUG_RETURN(0); + error_num = spider_write_sys_table_row(table); + DBUG_RETURN(error_num); } int spider_insert_or_update_table_sts( @@ -1378,7 +1420,9 @@ int spider_insert_or_update_table_sts( DBUG_RETURN(error_num); } if ((error_num = spider_write_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } else { if ((error_num = spider_update_sys_table_row(table, FALSE))) { @@ -1415,7 +1459,9 @@ int spider_insert_or_update_table_crd( DBUG_RETURN(error_num); } if ((error_num = spider_write_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } else { if ((error_num = spider_update_sys_table_row(table, FALSE))) { @@ -1444,7 +1490,9 @@ int spider_log_tables_link_failed( table->timestamp_field->set_time(); #endif if ((error_num = spider_write_sys_table_row(table))) + { DBUG_RETURN(error_num); + } DBUG_RETURN(0); } @@ -1479,7 +1527,9 @@ int spider_log_xa_failed( table->timestamp_field->set_time(); #endif if ((error_num = spider_write_sys_table_row(table))) + { DBUG_RETURN(error_num); + } DBUG_RETURN(0); } @@ -1509,7 +1559,9 @@ int spider_update_xa( table->use_all_columns(); spider_store_xa_status(table, status); if ((error_num = spider_update_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } DBUG_RETURN(0); @@ -1543,7 +1595,9 @@ int spider_update_tables_name( table->use_all_columns(); spider_store_tables_name(table, to, strlen(to)); if ((error_num = spider_update_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } roop_count++; } @@ -1588,7 +1642,9 @@ int spider_update_tables_priority( alter_table->tmp_link_statuses[roop_count] : SPIDER_LINK_STATUS_OK); if ((error_num = spider_write_sys_table_row(table))) + { DBUG_RETURN(error_num); + } roop_count++; } while (roop_count < (int) alter_table->all_link_count); DBUG_RETURN(0); @@ -1605,7 +1661,9 @@ int spider_update_tables_priority( spider_store_tables_link_status(table, alter_table->tmp_link_statuses[roop_count]); if ((error_num = spider_update_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } } while (TRUE) @@ -1624,7 +1682,9 @@ int spider_update_tables_priority( DBUG_RETURN(error_num); } if ((error_num = spider_delete_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } roop_count++; } @@ -1661,12 +1721,23 @@ int spider_update_tables_link_status( table->use_all_columns(); spider_store_tables_link_status(table, link_status); if ((error_num = spider_update_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } DBUG_RETURN(0); } +int spider_update_sys_table( + TABLE *table +) { + int error_num; + DBUG_ENTER("spider_update_sys_table"); + error_num = spider_update_sys_table_row(table); + DBUG_RETURN(error_num); +} + int spider_delete_xa( TABLE *table, XID *xid @@ -1689,7 +1760,9 @@ int spider_delete_xa( DBUG_RETURN(ER_SPIDER_XA_NOT_EXISTS_NUM); } else { if ((error_num = spider_delete_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } DBUG_RETURN(0); @@ -1752,7 +1825,9 @@ int spider_delete_tables( break; else { if ((error_num = spider_delete_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } roop_count++; } @@ -1783,7 +1858,9 @@ int spider_delete_table_sts( DBUG_RETURN(0); } else { if ((error_num = spider_delete_sys_table_row(table))) + { DBUG_RETURN(error_num); + } } DBUG_RETURN(0); @@ -2386,7 +2463,7 @@ void spider_get_sys_table_sts_info( *index_file_length = (ulonglong) table->field[4]->val_int(); *records = (ha_rows) table->field[5]->val_int(); *mean_rec_length = (ulong) table->field[6]->val_int(); - table->field[7]->get_date(&mysql_time, 0); + table->field[7]->get_date(&mysql_time, SPIDER_date_mode_t(0)); #ifdef MARIADB_BASE_VERSION *check_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -2394,7 +2471,7 @@ void spider_get_sys_table_sts_info( *check_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_my_bool); #endif - table->field[8]->get_date(&mysql_time, 0); + table->field[8]->get_date(&mysql_time, SPIDER_date_mode_t(0)); #ifdef MARIADB_BASE_VERSION *create_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -2402,7 +2479,7 @@ void spider_get_sys_table_sts_info( *create_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_my_bool); #endif - table->field[9]->get_date(&mysql_time, 0); + table->field[9]->get_date(&mysql_time, SPIDER_date_mode_t(0)); #ifdef MARIADB_BASE_VERSION *update_time = (time_t) my_system_gmt_sec(&mysql_time, ¬_used_long, ¬_used_uint); @@ -3207,27 +3284,37 @@ error: DBUG_RETURN(error_num); } +#ifdef SPIDER_use_LEX_CSTRING_for_Field_blob_constructor +TABLE *spider_mk_sys_tmp_table( + THD *thd, + TABLE *table, + TMP_TABLE_PARAM *tmp_tbl_prm, + const LEX_CSTRING *field_name, + CHARSET_INFO *cs +) +#else TABLE *spider_mk_sys_tmp_table( THD *thd, TABLE *table, TMP_TABLE_PARAM *tmp_tbl_prm, const char *field_name, CHARSET_INFO *cs -) { +) +#endif +{ Field_blob *field; Item_field *i_field; List i_list; TABLE *tmp_table; - LEX_CSTRING name= { field_name, strlen(field_name) }; DBUG_ENTER("spider_mk_sys_tmp_table"); #ifdef SPIDER_FIELD_FIELDPTR_REQUIRES_THDPTR if (!(field = new (thd->mem_root) Field_blob( - (uint32) 4294967295U, FALSE, &name, cs, TRUE))) + 4294967295U, FALSE, field_name, cs, TRUE))) goto error_alloc_field; #else if (!(field = new Field_blob( - 4294967295U, FALSE, &name, cs, TRUE))) + 4294967295U, FALSE, field_name, cs, TRUE))) goto error_alloc_field; #endif field->init(table); @@ -3245,7 +3332,7 @@ TABLE *spider_mk_sys_tmp_table( if (!(tmp_table = create_tmp_table(thd, tmp_tbl_prm, i_list, (ORDER*) NULL, FALSE, FALSE, TMP_TABLE_FORCE_MYISAM, - HA_POS_ERROR, &empty_clex_string))) + HA_POS_ERROR, &SPIDER_empty_string))) goto error_create_tmp_table; DBUG_RETURN(tmp_table); @@ -3270,6 +3357,17 @@ void spider_rm_sys_tmp_table( DBUG_VOID_RETURN; } +#ifdef SPIDER_use_LEX_CSTRING_for_Field_blob_constructor +TABLE *spider_mk_sys_tmp_table_for_result( + THD *thd, + TABLE *table, + TMP_TABLE_PARAM *tmp_tbl_prm, + const LEX_CSTRING *field_name1, + const LEX_CSTRING *field_name2, + const LEX_CSTRING *field_name3, + CHARSET_INFO *cs +) +#else TABLE *spider_mk_sys_tmp_table_for_result( THD *thd, TABLE *table, @@ -3278,23 +3376,22 @@ TABLE *spider_mk_sys_tmp_table_for_result( const char *field_name2, const char *field_name3, CHARSET_INFO *cs -) { +) +#endif +{ Field_blob *field1, *field2, *field3; Item_field *i_field1, *i_field2, *i_field3; List i_list; TABLE *tmp_table; - LEX_CSTRING name1= { field_name1, strlen(field_name1) }; - LEX_CSTRING name2= { field_name2, strlen(field_name2) }; - LEX_CSTRING name3= { field_name3, strlen(field_name3) }; DBUG_ENTER("spider_mk_sys_tmp_table_for_result"); #ifdef SPIDER_FIELD_FIELDPTR_REQUIRES_THDPTR if (!(field1 = new (thd->mem_root) Field_blob( - (uint32) 4294967295U, FALSE, &name1, cs, TRUE))) + 4294967295U, FALSE, field_name1, cs, TRUE))) goto error_alloc_field1; #else if (!(field1 = new Field_blob( - 4294967295U, FALSE, &name1, cs, TRUE))) + 4294967295U, FALSE, field_name1, cs, TRUE))) goto error_alloc_field1; #endif field1->init(table); @@ -3312,11 +3409,11 @@ TABLE *spider_mk_sys_tmp_table_for_result( #ifdef SPIDER_FIELD_FIELDPTR_REQUIRES_THDPTR if (!(field2 = new (thd->mem_root) Field_blob( - 4294967295U, FALSE, &name2, cs, TRUE))) + 4294967295U, FALSE, field_name2, cs, TRUE))) goto error_alloc_field2; #else if (!(field2 = new Field_blob( - 4294967295U, FALSE, &name2, cs, TRUE))) + 4294967295U, FALSE, field_name2, cs, TRUE))) goto error_alloc_field2; #endif field2->init(table); @@ -3334,7 +3431,7 @@ TABLE *spider_mk_sys_tmp_table_for_result( #ifdef SPIDER_FIELD_FIELDPTR_REQUIRES_THDPTR if (!(field3 = new (thd->mem_root) Field_blob( - 4294967295U, FALSE, &name3, cs, TRUE))) + 4294967295U, FALSE, field_name3, cs, TRUE))) goto error_alloc_field3; #else if (!(field3 = new Field_blob( @@ -3356,7 +3453,7 @@ TABLE *spider_mk_sys_tmp_table_for_result( if (!(tmp_table = create_tmp_table(thd, tmp_tbl_prm, i_list, (ORDER*) NULL, FALSE, FALSE, TMP_TABLE_FORCE_MYISAM, - HA_POS_ERROR, &empty_clex_string))) + HA_POS_ERROR, &SPIDER_empty_string))) goto error_create_tmp_table; DBUG_RETURN(tmp_table); diff --git a/storage/spider/spd_sys_table.h b/storage/spider/spd_sys_table.h index 009ef2ac8ca..857109edb38 100644 --- a/storage/spider/spd_sys_table.h +++ b/storage/spider/spd_sys_table.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2016 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -173,6 +173,11 @@ int spider_sys_index_first( const int idx ); +int spider_sys_index_last( + TABLE *table, + const int idx +); + int spider_sys_index_next( TABLE *table ); @@ -386,6 +391,10 @@ int spider_update_tables_link_status( long link_status ); +int spider_update_sys_table( + TABLE *table +); + int spider_delete_xa( TABLE *table, XID *xid @@ -618,6 +627,15 @@ int spider_sys_replace( bool *modified_non_trans_table ); +#ifdef SPIDER_use_LEX_CSTRING_for_Field_blob_constructor +TABLE *spider_mk_sys_tmp_table( + THD *thd, + TABLE *table, + TMP_TABLE_PARAM *tmp_tbl_prm, + const LEX_CSTRING *field_name, + CHARSET_INFO *cs +); +#else TABLE *spider_mk_sys_tmp_table( THD *thd, TABLE *table, @@ -625,6 +643,7 @@ TABLE *spider_mk_sys_tmp_table( const char *field_name, CHARSET_INFO *cs ); +#endif void spider_rm_sys_tmp_table( THD *thd, @@ -632,6 +651,17 @@ void spider_rm_sys_tmp_table( TMP_TABLE_PARAM *tmp_tbl_prm ); +#ifdef SPIDER_use_LEX_CSTRING_for_Field_blob_constructor +TABLE *spider_mk_sys_tmp_table_for_result( + THD *thd, + TABLE *table, + TMP_TABLE_PARAM *tmp_tbl_prm, + const LEX_CSTRING *field_name1, + const LEX_CSTRING *field_name2, + const LEX_CSTRING *field_name3, + CHARSET_INFO *cs +); +#else TABLE *spider_mk_sys_tmp_table_for_result( THD *thd, TABLE *table, @@ -641,6 +671,7 @@ TABLE *spider_mk_sys_tmp_table_for_result( const char *field_name3, CHARSET_INFO *cs ); +#endif void spider_rm_sys_tmp_table_for_result( THD *thd, diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 1940dd5aad9..1f220b193e5 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -1721,8 +1721,7 @@ int st_spider_param_string_parse::print_param_error() if ((share->param_name = spider_get_string_between_quote( \ start_ptr, TRUE, &connect_string_parse))) \ share->SPIDER_PARAM_STR_LEN(param_name) = strlen(share->param_name); \ - else \ - { \ + else { \ error_num = connect_string_parse.print_param_error(); \ goto error; \ } \ @@ -5219,15 +5218,20 @@ SPIDER_SHARE *spider_get_share( } if (!share->link_status_init) { - if ( - ( - table_share->tmp_table == NO_TMP_TABLE && - sql_command != SQLCOM_DROP_TABLE && - sql_command != SQLCOM_SHOW_CREATE - ) || - /* for alter change link status */ - sql_command == SQLCOM_ALTER_TABLE - ) { + /* + The link statuses need to be refreshed from the spider_tables table + if the operation: + - Is not a DROP TABLE on a permanent table; or + - Is an ALTER TABLE. + + Note that SHOW CREATE TABLE is not excluded, because the commands + that follow it require up-to-date link statuses. + */ + if ((table_share->tmp_table == NO_TMP_TABLE && + sql_command != SQLCOM_DROP_TABLE) || + /* for alter change link status */ + sql_command == SQLCOM_ALTER_TABLE) + { SPD_INIT_ALLOC_ROOT(&mem_root, 4096, 0, MYF(MY_WME)); init_mem_root = TRUE; if ( @@ -8965,7 +8969,9 @@ bool spider_check_direct_order_limit( int spider_set_direct_limit_offset( ha_spider *spider ) { +#ifndef SPIDER_ENGINE_CONDITION_PUSHDOWN_IS_ALWAYS_ON THD *thd = spider->trx->thd; +#endif st_select_lex *select_lex; longlong select_limit; longlong offset_limit; @@ -9037,7 +9043,11 @@ int spider_set_direct_limit_offset( DBUG_RETURN(FALSE); // ignore condition like 1=1 +#ifdef SPIDER_has_Item_with_subquery if (select_lex->where && select_lex->where->with_subquery()) +#else + if (select_lex->where && select_lex->where->with_subselect) +#endif DBUG_RETURN(FALSE); if ( @@ -9049,7 +9059,7 @@ int spider_set_direct_limit_offset( DBUG_RETURN(FALSE); // must not be derived table - if (&thd->lex->select_lex != select_lex) + if (SPIDER_get_linkage(select_lex) == DERIVED_TABLE_TYPE) DBUG_RETURN(FALSE); spider->direct_select_offset = offset_limit; @@ -9491,7 +9501,8 @@ int spider_discover_table_structure( uint collatelen = strlen(table_charset->name); if (str.reserve(SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_DEFAULT_CHARSET_LEN + csnamelen + SPIDER_SQL_COLLATE_LEN + collatelen + - SPIDER_SQL_CONNECTION_LEN + SPIDER_SQL_VALUE_QUOTE_LEN + SPIDER_SQL_CONNECTION_LEN + SPIDER_SQL_VALUE_QUOTE_LEN + + (share->comment.length * 2) )) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } @@ -9504,7 +9515,8 @@ int spider_discover_table_structure( str.q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); str.append_escape_string(share->comment.str, share->comment.length); if (str.reserve(SPIDER_SQL_CONNECTION_LEN + - (SPIDER_SQL_VALUE_QUOTE_LEN * 2))) + (SPIDER_SQL_VALUE_QUOTE_LEN * 2) + + (share->connect_string.length * 2))) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index e09c7fa6c45..565665dc6f7 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2017 Kentoku Shiba +/* Copyright (C) 2008-2018 Kentoku Shiba 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 @@ -26,7 +26,6 @@ #include "sql_class.h" #include "sql_partition.h" #include "records.h" -#include "tztime.h" #endif #include "spd_err.h" #include "spd_param.h" @@ -1648,9 +1647,7 @@ int spider_check_and_set_sql_log_off( if (internal_sql_log_off) { spider_conn_queue_sql_log_off(conn, TRUE); - } - else - { + } else { spider_conn_queue_sql_log_off(conn, FALSE); } } @@ -2764,7 +2761,8 @@ int spider_initinal_xa_recover( FALSE, FALSE); } SPD_INIT_ALLOC_ROOT(&mem_root, 4096, 0, MYF(MY_WME)); - while ((!(read_record->read_record())) && cnt < (int) len) + while ((!(read_record->SPIDER_read_record_read_record(read_record))) && + cnt < (int) len) { spider_get_sys_xid(table_xa, &xid_list[cnt], &mem_root); cnt++; @@ -2813,7 +2811,7 @@ int spider_internal_xa_commit_by_xid( SPIDER_TRX *trx, XID* xid ) { - TABLE *table_xa, *table_xa_member= 0; + TABLE *table_xa, *table_xa_member = 0; int error_num; char xa_key[MAX_KEY_LENGTH]; char xa_member_key[MAX_KEY_LENGTH]; @@ -3048,7 +3046,7 @@ int spider_internal_xa_rollback_by_xid( SPIDER_TRX *trx, XID* xid ) { - TABLE *table_xa, *table_xa_member= 0; + TABLE *table_xa, *table_xa_member = 0; int error_num; char xa_key[MAX_KEY_LENGTH]; char xa_member_key[MAX_KEY_LENGTH]; From 3cb7c5f27bbd267e3efd69b1b312711754261801 Mon Sep 17 00:00:00 2001 From: Kentoku Date: Tue, 20 Nov 2018 05:43:49 +0900 Subject: [PATCH 10/91] MDEV-16279 Spider crashes on CHECKSUM TABLE with spider_quick_mode=3 The fields of the temporary table were not created in create_tmp_table function. Because item->const_item() was true. But the temporary tables that is created by Spider are always used all columns. So Spider should call create_tmp_table function with TMP_TABLE_ALL_COLUMNS flag. --- ...hecksum_table_with_quick_mode_3_deinit.inc | 14 ++ .../checksum_table_with_quick_mode_3_init.inc | 29 ++++ .../spider/mysql-test/spider/bugfix/my.cnf | 2 + .../mysql-test/spider/bugfix/my_1_1.cnf | 44 ++++++ .../mysql-test/spider/bugfix/my_2_1.cnf | 56 ++++++++ .../mysql-test/spider/bugfix/my_2_2.cnf | 38 ++++++ .../mysql-test/spider/bugfix/my_2_3.cnf | 8 ++ .../mysql-test/spider/bugfix/my_3_1.cnf | 11 ++ .../mysql-test/spider/bugfix/my_3_2.cnf | 9 ++ .../mysql-test/spider/bugfix/my_3_3.cnf | 9 ++ .../mysql-test/spider/bugfix/my_4_1.cnf | 9 ++ .../r/checksum_table_with_quick_mode_3.result | 100 ++++++++++++++ .../spider/mysql-test/spider/bugfix/suite.opt | 1 + .../spider/mysql-test/spider/bugfix/suite.pm | 12 ++ .../t/checksum_table_with_quick_mode_3.cnf | 3 + .../t/checksum_table_with_quick_mode_3.test | 72 ++++++++++ ...hecksum_table_with_quick_mode_3_deinit.inc | 16 +++ .../checksum_table_with_quick_mode_3_init.inc | 33 +++++ .../r/checksum_table_with_quick_mode_3.result | 104 +++++++++++++++ .../t/checksum_table_with_quick_mode_3.test | 126 ++++++++++++++++++ storage/spider/spd_sys_table.cc | 6 +- 21 files changed, 700 insertions(+), 2 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_deinit.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_init.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/my.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/my_1_1.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/my_2_1.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/my_2_2.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/my_2_3.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/my_3_1.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/my_3_2.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/my_3_3.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/my_4_1.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/r/checksum_table_with_quick_mode_3.result create mode 100644 storage/spider/mysql-test/spider/bugfix/suite.opt create mode 100644 storage/spider/mysql-test/spider/bugfix/suite.pm create mode 100644 storage/spider/mysql-test/spider/bugfix/t/checksum_table_with_quick_mode_3.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/checksum_table_with_quick_mode_3.test create mode 100644 storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_init.inc create mode 100644 storage/spider/mysql-test/spider/r/checksum_table_with_quick_mode_3.result create mode 100644 storage/spider/mysql-test/spider/t/checksum_table_with_quick_mode_3.test diff --git a/storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_deinit.inc new file mode 100644 index 00000000000..47f6df9437e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_deinit.inc @@ -0,0 +1,14 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--connection master_1 +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_init.inc b/storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_init.inc new file mode 100644 index 00000000000..bf2d9163b9a --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_init.inc @@ -0,0 +1,29 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--connection master_1 +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 3; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; diff --git a/storage/spider/mysql-test/spider/bugfix/my.cnf b/storage/spider/mysql-test/spider/bugfix/my.cnf new file mode 100644 index 00000000000..b7f76a630cc --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/my.cnf @@ -0,0 +1,2 @@ +!include include/default_mysqld.cnf +!include my_1_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/my_1_1.cnf b/storage/spider/mysql-test/spider/bugfix/my_1_1.cnf new file mode 100644 index 00000000000..5f17295d895 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/my_1_1.cnf @@ -0,0 +1,44 @@ +[mysqld.1.1] +log-bin= master-bin +loose_handlersocket_port= 20000 +loose_handlersocket_port_wr= 20001 +loose_handlersocket_threads= 2 +loose_handlersocket_threads_wr= 1 +loose_handlersocket_support_merge_table= 0 +loose_handlersocket_direct_update_mode= 2 +loose_handlersocket_unlimited_boundary= 65536 +loose_handlersocket_bulk_insert= 0 +loose_handlersocket_bulk_insert_timeout= 0 +loose_handlersocket_general_log= 1 +loose_handlersocket_timeout= 30 +loose_handlersocket_close_table_interval=2 +open_files_limit= 4096 +loose_partition= 1 + +[ENV] +USE_GEOMETRY_TEST= 1 +USE_FULLTEXT_TEST= 1 +USE_HA_TEST= 1 +USE_GENERAL_LOG= 1 +USE_REPLICATION= 1 +MASTER_1_MYPORT= @mysqld.1.1.port +MASTER_1_HSRPORT= 20000 +MASTER_1_HSWPORT= 20001 +MASTER_1_MYSOCK= @mysqld.1.1.socket +MASTER_1_ENGINE_TYPE= Spider +#MASTER_1_ENGINE_TYPE= MyISAM +MASTER_1_ENGINE= ENGINE=Spider +MASTER_1_CHARSET= DEFAULT CHARSET=utf8 +MASTER_1_ENGINE2= ENGINE=MyISAM +MASTER_1_CHARSET2= DEFAULT CHARSET=utf8 +MASTER_1_CHARSET3= DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci + +STR_SEMICOLON= ; + +#The followings are set in include/init_xxx.inc files +# MASTER_1_COMMENT_2_1 +# MASTER_1_COMMENT2_2_1 +# MASTER_1_COMMENT3_2_1 +# MASTER_1_COMMENT4_2_1 +# MASTER_1_COMMENT5_2_1 +# MASTER_1_COMMENT_P_2_1 diff --git a/storage/spider/mysql-test/spider/bugfix/my_2_1.cnf b/storage/spider/mysql-test/spider/bugfix/my_2_1.cnf new file mode 100644 index 00000000000..24161645607 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/my_2_1.cnf @@ -0,0 +1,56 @@ +[mysqld.2.1] +loose_handlersocket_port= 20002 +loose_handlersocket_port_wr= 20003 +loose_handlersocket_threads= 2 +loose_handlersocket_threads_wr= 1 +loose_handlersocket_support_merge_table= 0 +loose_handlersocket_direct_update_mode= 2 +loose_handlersocket_unlimited_boundary= 65536 +loose_handlersocket_bulk_insert= 0 +loose_handlersocket_bulk_insert_timeout= 0 +loose_handlersocket_general_log= 1 +loose_handlersocket_timeout= 30 +loose_handlersocket_close_table_interval=2 +open_files_limit= 4096 + +[ENV] +USE_CHILD_GROUP2= 1 +OUTPUT_CHILD_GROUP2= 0 +CHILD2_1_MYPORT= @mysqld.2.1.port +CHILD2_1_HSRPORT= 20002 +CHILD2_1_HSWPORT= 20003 +CHILD2_1_MYSOCK= @mysqld.2.1.socket +CHILD2_1_ENGINE_TYPE= InnoDB +CHILD2_1_ENGINE= ENGINE=InnoDB +CHILD2_1_CHARSET= DEFAULT CHARSET=utf8 +CHILD2_1_CHARSET2= DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci +CHILD2_1_FT_MYPORT= @mysqld.2.1.port +CHILD2_1_FT_MYSOCK= @mysqld.2.1.socket +CHILD2_1_FT_ENGINE_TYPE= MyISAM +CHILD2_1_FT_ENGINE= ENGINE=MyISAM +CHILD2_1_FT_CHARSET= DEFAULT CHARSET=utf8 +CHILD2_1_GM_MYPORT= @mysqld.2.1.port +CHILD2_1_GM_MYSOCK= @mysqld.2.1.socket +CHILD2_1_GM_ENGINE_TYPE= MyISAM +CHILD2_1_GM_ENGINE= ENGINE=MyISAM +CHILD2_1_GM_CHARSET= DEFAULT CHARSET=utf8 + +#The followings are set in include/init_xxx.inc files +# CHILD2_1_DROP_TABLES +# CHILD2_1_CREATE_TABLES +# CHILD2_1_SELECT_TABLES +# CHILD2_1_DROP_TABLES2 +# CHILD2_1_CREATE_TABLES2 +# CHILD2_1_SELECT_TABLES2 +# CHILD2_1_DROP_TABLES3 +# CHILD2_1_CREATE_TABLES3 +# CHILD2_1_SELECT_TABLES3 +# CHILD2_1_DROP_TABLES4 +# CHILD2_1_CREATE_TABLES4 +# CHILD2_1_SELECT_TABLES4 +# CHILD2_1_DROP_TABLES5 +# CHILD2_1_CREATE_TABLES5 +# CHILD2_1_SELECT_TABLES5 +# CHILD2_1_DROP_TABLES6 +# CHILD2_1_CREATE_TABLES6 +# CHILD2_1_SELECT_TABLES6 diff --git a/storage/spider/mysql-test/spider/bugfix/my_2_2.cnf b/storage/spider/mysql-test/spider/bugfix/my_2_2.cnf new file mode 100644 index 00000000000..2d3c2a89a7d --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/my_2_2.cnf @@ -0,0 +1,38 @@ +[mysqld.2.2] +loose_handlersocket_port= 20004 +loose_handlersocket_port_wr= 20005 +loose_handlersocket_threads= 2 +loose_handlersocket_threads_wr= 1 +loose_handlersocket_support_merge_table= 0 +loose_handlersocket_direct_update_mode= 2 +loose_handlersocket_unlimited_boundary= 65536 +loose_handlersocket_bulk_insert= 0 +loose_handlersocket_bulk_insert_timeout= 0 +loose_handlersocket_general_log= 1 +loose_handlersocket_timeout= 30 +loose_handlersocket_close_table_interval=2 +open_files_limit= 4096 + +[ENV] +CHILD2_2_MYPORT= @mysqld.2.2.port +CHILD2_2_HSRPORT= 20004 +CHILD2_2_HSWPORT= 20005 +CHILD2_2_MYSOCK= @mysqld.2.2.socket +CHILD2_2_ENGINE_TYPE= InnoDB +CHILD2_2_ENGINE= ENGINE=InnoDB +CHILD2_2_CHARSET= DEFAULT CHARSET=utf8 +CHILD2_2_FT_MYPORT= @mysqld.2.2.port +CHILD2_2_FT_MYSOCK= @mysqld.2.2.socket +CHILD2_2_FT_ENGINE_TYPE= MyISAM +CHILD2_2_FT_ENGINE= ENGINE=MyISAM +CHILD2_2_FT_CHARSET= DEFAULT CHARSET=utf8 +CHILD2_2_GM_MYPORT= @mysqld.2.2.port +CHILD2_2_GM_MYSOCK= @mysqld.2.2.socket +CHILD2_2_GM_ENGINE_TYPE= MyISAM +CHILD2_2_GM_ENGINE= ENGINE=MyISAM +CHILD2_2_GM_CHARSET= DEFAULT CHARSET=utf8 + +#The followings are set in include/init_xxx.inc files +# CHILD2_2_DROP_TABLES +# CHILD2_2_CREATE_TABLES +# CHILD2_2_SELECT_TABLES diff --git a/storage/spider/mysql-test/spider/bugfix/my_2_3.cnf b/storage/spider/mysql-test/spider/bugfix/my_2_3.cnf new file mode 100644 index 00000000000..024da651e0c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/my_2_3.cnf @@ -0,0 +1,8 @@ +[mysqld.2.3] + +[ENV] +CHILD2_3_MYPORT= @mysqld.2.3.port +CHILD2_3_MYSOCK= @mysqld.2.3.socket +CHILD2_3_ENGINE_TYPE= InnoDB +CHILD2_3_ENGINE= ENGINE=InnoDB +CHILD2_3_CHARSET= DEFAULT CHARSET=utf8 diff --git a/storage/spider/mysql-test/spider/bugfix/my_3_1.cnf b/storage/spider/mysql-test/spider/bugfix/my_3_1.cnf new file mode 100644 index 00000000000..fad21607789 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/my_3_1.cnf @@ -0,0 +1,11 @@ +[mysqld.3.1] +loose_partition= 1 + +[ENV] +USE_CHILD_GROUP3= 1 +OUTPUT_CHILD_GROUP3= 0 +CHILD3_1_MYPORT= @mysqld.3.1.port +CHILD3_1_MYSOCK= @mysqld.3.1.socket +CHILD3_1_ENGINE_TYPE= InnoDB +CHILD3_1_ENGINE= ENGINE=InnoDB +CHILD3_1_CHARSET= DEFAULT CHARSET=utf8 diff --git a/storage/spider/mysql-test/spider/bugfix/my_3_2.cnf b/storage/spider/mysql-test/spider/bugfix/my_3_2.cnf new file mode 100644 index 00000000000..6f027b6f525 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/my_3_2.cnf @@ -0,0 +1,9 @@ +[mysqld.3.2] +loose_partition= 1 + +[ENV] +CHILD3_2_MYPORT= @mysqld.3.2.port +CHILD3_2_MYSOCK= @mysqld.3.2.socket +CHILD3_2_ENGINE_TYPE= InnoDB +CHILD3_2_ENGINE= ENGINE=InnoDB +CHILD3_2_CHARSET= DEFAULT CHARSET=utf8 diff --git a/storage/spider/mysql-test/spider/bugfix/my_3_3.cnf b/storage/spider/mysql-test/spider/bugfix/my_3_3.cnf new file mode 100644 index 00000000000..fbb33694738 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/my_3_3.cnf @@ -0,0 +1,9 @@ +[mysqld.3.3] +loose_partition= 1 + +[ENV] +CHILD3_3_MYPORT= @mysqld.3.3.port +CHILD3_3_MYSOCK= @mysqld.3.3.socket +CHILD3_3_ENGINE_TYPE= InnoDB +CHILD3_3_ENGINE= ENGINE=InnoDB +CHILD3_3_CHARSET= DEFAULT CHARSET=utf8 diff --git a/storage/spider/mysql-test/spider/bugfix/my_4_1.cnf b/storage/spider/mysql-test/spider/bugfix/my_4_1.cnf new file mode 100644 index 00000000000..d1812a48b68 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/my_4_1.cnf @@ -0,0 +1,9 @@ +[mysqld.4.1] +loose_partition= 1 + +[ENV] +SLAVE1_1_MYPORT= @mysqld.4.1.port +SLAVE1_1_MYSOCK= @mysqld.4.1.socket +SLAVE1_1_ENGINE_TYPE= MyISAM +SLAVE1_1_ENGINE= ENGINE=MyISAM +SLAVE1_1_CHARSET= DEFAULT CHARSET=utf8 diff --git a/storage/spider/mysql-test/spider/bugfix/r/checksum_table_with_quick_mode_3.result b/storage/spider/mysql-test/spider/bugfix/r/checksum_table_with_quick_mode_3.result new file mode 100644 index 00000000000..eae4895411e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/checksum_table_with_quick_mode_3.result @@ -0,0 +1,100 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection master_1; +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 3; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; + +this test is for MDEV-16279 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +FLUSH TABLES; + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +CHECKSUM TABLE tbl_a EXTENDED; +Table Checksum +auto_test_local.tbl_a 1061386331 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/suite.opt b/storage/spider/mysql-test/spider/bugfix/suite.opt new file mode 100644 index 00000000000..672a3b37d4f --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/suite.opt @@ -0,0 +1 @@ +--loose-innodb --loose-skip-performance-schema diff --git a/storage/spider/mysql-test/spider/bugfix/suite.pm b/storage/spider/mysql-test/spider/bugfix/suite.pm new file mode 100644 index 00000000000..f106147deb6 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/suite.pm @@ -0,0 +1,12 @@ +package My::Suite::Spider; + +@ISA = qw(My::Suite); + +return "No Spider engine" unless $ENV{HA_SPIDER_SO}; +return "Not run for embedded server" if $::opt_embedded_server; +return "Test needs --big-test" unless $::opt_big_test; + +sub is_default { 1 } + +bless { }; + diff --git a/storage/spider/mysql-test/spider/bugfix/t/checksum_table_with_quick_mode_3.cnf b/storage/spider/mysql-test/spider/bugfix/t/checksum_table_with_quick_mode_3.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/checksum_table_with_quick_mode_3.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/checksum_table_with_quick_mode_3.test b/storage/spider/mysql-test/spider/bugfix/t/checksum_table_with_quick_mode_3.test new file mode 100644 index 00000000000..5dc4a88c842 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/checksum_table_with_quick_mode_3.test @@ -0,0 +1,72 @@ +--source ../include/checksum_table_with_quick_mode_3_init.inc +--echo +--echo this test is for MDEV-16279 +--echo +--echo drop and create databases + +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +FLUSH TABLES; + +--echo +--echo select test 1 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +CHECKSUM TABLE tbl_a EXTENDED; + +--connection child2_1 +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/checksum_table_with_quick_mode_3_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_deinit.inc b/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_deinit.inc new file mode 100644 index 00000000000..d551f5a4af3 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_deinit.inc @@ -0,0 +1,16 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--connection master_1 +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_init.inc b/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_init.inc new file mode 100644 index 00000000000..9ec61a1cb77 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_init.inc @@ -0,0 +1,33 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 +--connection master_1 +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 3; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; diff --git a/storage/spider/mysql-test/spider/r/checksum_table_with_quick_mode_3.result b/storage/spider/mysql-test/spider/r/checksum_table_with_quick_mode_3.result new file mode 100644 index 00000000000..ee8e1f056f3 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/checksum_table_with_quick_mode_3.result @@ -0,0 +1,104 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 +connection master_1; +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 3; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +FLUSH TABLES; + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +CHECKSUM TABLE tbl_a EXTENDED; +Table Checksum +auto_test_local.tbl_a 1061386331 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/t/checksum_table_with_quick_mode_3.test b/storage/spider/mysql-test/spider/t/checksum_table_with_quick_mode_3.test new file mode 100644 index 00000000000..d108fda7e41 --- /dev/null +++ b/storage/spider/mysql-test/spider/t/checksum_table_with_quick_mode_3.test @@ -0,0 +1,126 @@ +--source ../include/checksum_table_with_quick_mode_3_init.inc +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_CREATE_TABLES; + } + eval $CHILD2_1_CREATE_TABLES; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +FLUSH TABLES; + +--echo +--echo select test 1 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +CHECKSUM TABLE tbl_a EXTENDED; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/checksum_table_with_quick_mode_3_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index 14f80b41108..cd1c56a077e 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -3331,7 +3331,8 @@ TABLE *spider_mk_sys_tmp_table( goto error_push_item; if (!(tmp_table = create_tmp_table(thd, tmp_tbl_prm, - i_list, (ORDER*) NULL, FALSE, FALSE, TMP_TABLE_FORCE_MYISAM, + i_list, (ORDER*) NULL, FALSE, FALSE, + (TMP_TABLE_FORCE_MYISAM | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR, &SPIDER_empty_string))) goto error_create_tmp_table; DBUG_RETURN(tmp_table); @@ -3452,7 +3453,8 @@ TABLE *spider_mk_sys_tmp_table_for_result( goto error_push_item3; if (!(tmp_table = create_tmp_table(thd, tmp_tbl_prm, - i_list, (ORDER*) NULL, FALSE, FALSE, TMP_TABLE_FORCE_MYISAM, + i_list, (ORDER*) NULL, FALSE, FALSE, + (TMP_TABLE_FORCE_MYISAM | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR, &SPIDER_empty_string))) goto error_create_tmp_table; DBUG_RETURN(tmp_table); From bef6b197fc2555be357642ec81851d240eec5aa7 Mon Sep 17 00:00:00 2001 From: Kentoku Date: Fri, 30 Nov 2018 03:17:08 +0900 Subject: [PATCH 11/91] MDEV-16520 Out-Of-Memory running big aggregate query on Spider Engine Change default value of the followings quick_mode 0 -> 3 quick_page_size 100 -> 1024 Add the following parameter for limiting result page size by byte - quick_page_byte(qpb) Number of bytes in a page when acquisition one by one. When quick_mode is 1 or 2, Spider stores at least 1 record even if quick_page_byte is smaller than 1 record. When quick_mode is 3, quick_page_byte is used for judging using temporary table. That is given to priority when server parameter spider_quick_page_byte is set. The default value is 10485760 Fix "out of sync" issue at using quick_mode = 1 or 2 --- storage/spider/ha_spider.cc | 2 + storage/spider/hs_client/hstcpcli.cpp | 25 +- storage/spider/hs_client/hstcpcli.hpp | 3 + .../spider/include/quick_mode_0_deinit.inc | 21 + .../spider/include/quick_mode_0_init.inc | 55 ++ .../spider/include/quick_mode_1_deinit.inc | 21 + .../spider/include/quick_mode_1_init.inc | 55 ++ .../spider/include/quick_mode_2_deinit.inc | 21 + .../spider/include/quick_mode_2_init.inc | 55 ++ .../spider/include/quick_mode_3_deinit.inc | 21 + .../spider/include/quick_mode_3_init.inc | 55 ++ .../mysql-test/spider/r/quick_mode_0.result | 515 ++++++++++++++++++ .../mysql-test/spider/r/quick_mode_1.result | 515 ++++++++++++++++++ .../mysql-test/spider/r/quick_mode_2.result | 515 ++++++++++++++++++ .../mysql-test/spider/r/quick_mode_3.result | 515 ++++++++++++++++++ .../mysql-test/spider/t/quick_mode_0.test | 309 +++++++++++ .../mysql-test/spider/t/quick_mode_1.test | 309 +++++++++++ .../mysql-test/spider/t/quick_mode_2.test | 309 +++++++++++ .../mysql-test/spider/t/quick_mode_3.test | 309 +++++++++++ storage/spider/spd_conn.cc | 1 + storage/spider/spd_db_conn.cc | 95 +++- storage/spider/spd_db_conn.h | 4 + storage/spider/spd_db_handlersocket.cc | 20 +- storage/spider/spd_db_handlersocket.h | 2 + storage/spider/spd_db_include.h | 2 + storage/spider/spd_db_mysql.cc | 35 +- storage/spider/spd_db_mysql.h | 2 + storage/spider/spd_db_oracle.cc | 11 + storage/spider/spd_db_oracle.h | 2 + storage/spider/spd_include.h | 1 + storage/spider/spd_param.cc | 26 + storage/spider/spd_param.h | 4 + storage/spider/spd_table.cc | 11 +- 33 files changed, 3816 insertions(+), 30 deletions(-) create mode 100644 storage/spider/mysql-test/spider/include/quick_mode_0_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/quick_mode_0_init.inc create mode 100644 storage/spider/mysql-test/spider/include/quick_mode_1_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/quick_mode_1_init.inc create mode 100644 storage/spider/mysql-test/spider/include/quick_mode_2_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/quick_mode_2_init.inc create mode 100644 storage/spider/mysql-test/spider/include/quick_mode_3_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/quick_mode_3_init.inc create mode 100644 storage/spider/mysql-test/spider/r/quick_mode_0.result create mode 100644 storage/spider/mysql-test/spider/r/quick_mode_1.result create mode 100644 storage/spider/mysql-test/spider/r/quick_mode_2.result create mode 100644 storage/spider/mysql-test/spider/r/quick_mode_3.result create mode 100644 storage/spider/mysql-test/spider/t/quick_mode_0.test create mode 100644 storage/spider/mysql-test/spider/t/quick_mode_1.test create mode 100644 storage/spider/mysql-test/spider/t/quick_mode_2.test create mode 100644 storage/spider/mysql-test/spider/t/quick_mode_3.test diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index 8471af40289..e60355958bd 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -7378,6 +7378,8 @@ int ha_spider::rnd_init( #endif if (quick_targets[roop_count]) { + spider_db_free_one_quick_result( + (SPIDER_RESULT *) result_list.current); DBUG_ASSERT(quick_targets[roop_count] == conns[roop_count]->quick_target); DBUG_PRINT("info", ("spider conn[%p]->quick_target=NULL", diff --git a/storage/spider/hs_client/hstcpcli.cpp b/storage/spider/hs_client/hstcpcli.cpp index 2cb37c7be9d..4c93b5a3a49 100644 --- a/storage/spider/hs_client/hstcpcli.cpp +++ b/storage/spider/hs_client/hstcpcli.cpp @@ -67,6 +67,8 @@ struct hstcpcli : public hstcpcli_i, private noncopyable { virtual int get_result(hstresult& result); virtual const string_ref *get_next_row(); virtual const string_ref *get_next_row_from_result(hstresult& result); + virtual size_t get_row_size(); + virtual size_t get_row_size_from_result(hstresult& result); virtual void response_buf_remove(); virtual int get_error_code(); virtual String& get_error(); @@ -93,6 +95,7 @@ struct hstcpcli : public hstcpcli_i, private noncopyable { string_buffer writebuf; size_t response_end_offset; /* incl newline */ size_t cur_row_offset; + size_t cur_row_size; size_t num_flds; size_t num_req_bufd; /* buffered but not yet sent */ size_t num_req_sent; /* sent but not yet received */ @@ -104,8 +107,9 @@ struct hstcpcli : public hstcpcli_i, private noncopyable { }; hstcpcli::hstcpcli(const socket_args& args) - : sargs(args), response_end_offset(0), cur_row_offset(0), num_flds(0), - num_req_bufd(0), num_req_sent(0), num_req_rcvd(0), error_code(0), errno_buf(0) + : sargs(args), response_end_offset(0), cur_row_offset(0), cur_row_size(0), + num_flds(0), num_req_bufd(0), num_req_sent(0), num_req_rcvd(0), + error_code(0), errno_buf(0) { String err; SPD_INIT_DYNAMIC_ARRAY2(&flds, sizeof(string_ref), NULL, 16, 16, MYF(MY_WME)); @@ -503,6 +507,7 @@ hstcpcli::response_recv(size_t& num_flds_r) } return set_error(resp_code, e); } + cur_row_size = 0; cur_row_offset = start - readbuf.begin(); DBG(fprintf(stderr, "[%s] ro=%zu eol=%zu\n", String(readbuf.begin(), readbuf.begin() + response_end_offset) @@ -529,6 +534,7 @@ hstcpcli::get_result(hstresult& result) result.readbuf.space_wrote(response_end_offset); result.response_end_offset = response_end_offset; result.num_flds = num_flds; + result.cur_row_size = cur_row_size; result.cur_row_offset = cur_row_offset; if (result.flds.max_element < num_flds) { @@ -566,6 +572,7 @@ hstcpcli::get_next_row() ((string_ref *) flds.buffer)[i] = string_ref(fld_begin, wp); } } + cur_row_size = start - (readbuf.begin() + cur_row_offset); cur_row_offset = start - readbuf.begin(); return (string_ref *) flds.buffer; } @@ -597,10 +604,24 @@ hstcpcli::get_next_row_from_result(hstresult& result) ((string_ref *) result.flds.buffer)[i] = string_ref(fld_begin, wp); } } + result.cur_row_size = + start - (result.readbuf.begin() + result.cur_row_offset); result.cur_row_offset = start - result.readbuf.begin(); return (string_ref *) result.flds.buffer; } +size_t +hstcpcli::get_row_size() +{ + return cur_row_size; +} + +size_t +hstcpcli::get_row_size_from_result(hstresult& result) +{ + return result.cur_row_size; +} + void hstcpcli::response_buf_remove() { diff --git a/storage/spider/hs_client/hstcpcli.hpp b/storage/spider/hs_client/hstcpcli.hpp index d153b19cf9b..6894716e469 100644 --- a/storage/spider/hs_client/hstcpcli.hpp +++ b/storage/spider/hs_client/hstcpcli.hpp @@ -46,6 +46,7 @@ struct hstresult { size_t response_end_offset; size_t num_flds; size_t cur_row_offset; + size_t cur_row_size; DYNAMIC_ARRAY flds; }; @@ -71,6 +72,8 @@ struct hstcpcli_i { virtual int get_result(hstresult& result) = 0; virtual const string_ref *get_next_row() = 0; virtual const string_ref *get_next_row_from_result(hstresult& result) = 0; + virtual size_t get_row_size() = 0; + virtual size_t get_row_size_from_result(hstresult& result) = 0; virtual void response_buf_remove() = 0; virtual int get_error_code() = 0; virtual String& get_error() = 0; diff --git a/storage/spider/mysql-test/spider/include/quick_mode_0_deinit.inc b/storage/spider/mysql-test/spider/include/quick_mode_0_deinit.inc new file mode 100644 index 00000000000..72d09f54316 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/quick_mode_0_deinit.inc @@ -0,0 +1,21 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $MASTER_1_COMMENT_2_2= $MASTER_1_COMMENT_2_2_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP +--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP +--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--connection master_1 +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/quick_mode_0_init.inc b/storage/spider/mysql-test/spider/include/quick_mode_0_init.inc new file mode 100644 index 00000000000..92afb3bf10b --- /dev/null +++ b/storage/spider/mysql-test/spider/include/quick_mode_0_init.inc @@ -0,0 +1,55 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $MASTER_1_COMMENT_2_2_BACKUP= $MASTER_1_COMMENT_2_2 +let $MASTER_1_COMMENT_2_2= + COMMENT='table "tbl_b", srv "s_2_2"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES +let $CHILD2_2_DROP_TABLES= + DROP TABLE IF EXISTS tbl_b; +--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES +let $CHILD2_2_CREATE_TABLES= + CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET; +--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES +let $CHILD2_2_SELECT_TABLES= + SELECT pkey FROM tbl_b ORDER BY pkey; +let $CHILD2_2_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 +--connection master_1 +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 0; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; +let $MASTER_1_SET_QUICK_PAGE_BYTE_6= + set session spider_quick_page_byte= 6; +let $MASTER_1_SET_QUICK_PAGE_BYTE_0= + set session spider_quick_page_byte= 0; diff --git a/storage/spider/mysql-test/spider/include/quick_mode_1_deinit.inc b/storage/spider/mysql-test/spider/include/quick_mode_1_deinit.inc new file mode 100644 index 00000000000..72d09f54316 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/quick_mode_1_deinit.inc @@ -0,0 +1,21 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $MASTER_1_COMMENT_2_2= $MASTER_1_COMMENT_2_2_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP +--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP +--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--connection master_1 +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/quick_mode_1_init.inc b/storage/spider/mysql-test/spider/include/quick_mode_1_init.inc new file mode 100644 index 00000000000..cc5a847fdc0 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/quick_mode_1_init.inc @@ -0,0 +1,55 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $MASTER_1_COMMENT_2_2_BACKUP= $MASTER_1_COMMENT_2_2 +let $MASTER_1_COMMENT_2_2= + COMMENT='table "tbl_b", srv "s_2_2"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES +let $CHILD2_2_DROP_TABLES= + DROP TABLE IF EXISTS tbl_b; +--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES +let $CHILD2_2_CREATE_TABLES= + CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET; +--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES +let $CHILD2_2_SELECT_TABLES= + SELECT pkey FROM tbl_b ORDER BY pkey; +let $CHILD2_2_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 +--connection master_1 +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 1; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; +let $MASTER_1_SET_QUICK_PAGE_BYTE_6= + set session spider_quick_page_byte= 6; +let $MASTER_1_SET_QUICK_PAGE_BYTE_0= + set session spider_quick_page_byte= 0; diff --git a/storage/spider/mysql-test/spider/include/quick_mode_2_deinit.inc b/storage/spider/mysql-test/spider/include/quick_mode_2_deinit.inc new file mode 100644 index 00000000000..72d09f54316 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/quick_mode_2_deinit.inc @@ -0,0 +1,21 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $MASTER_1_COMMENT_2_2= $MASTER_1_COMMENT_2_2_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP +--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP +--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--connection master_1 +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/quick_mode_2_init.inc b/storage/spider/mysql-test/spider/include/quick_mode_2_init.inc new file mode 100644 index 00000000000..3a16bb1dc63 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/quick_mode_2_init.inc @@ -0,0 +1,55 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $MASTER_1_COMMENT_2_2_BACKUP= $MASTER_1_COMMENT_2_2 +let $MASTER_1_COMMENT_2_2= + COMMENT='table "tbl_b", srv "s_2_2"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES +let $CHILD2_2_DROP_TABLES= + DROP TABLE IF EXISTS tbl_b; +--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES +let $CHILD2_2_CREATE_TABLES= + CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET; +--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES +let $CHILD2_2_SELECT_TABLES= + SELECT pkey FROM tbl_b ORDER BY pkey; +let $CHILD2_2_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 +--connection master_1 +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 2; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; +let $MASTER_1_SET_QUICK_PAGE_BYTE_6= + set session spider_quick_page_byte= 6; +let $MASTER_1_SET_QUICK_PAGE_BYTE_0= + set session spider_quick_page_byte= 0; diff --git a/storage/spider/mysql-test/spider/include/quick_mode_3_deinit.inc b/storage/spider/mysql-test/spider/include/quick_mode_3_deinit.inc new file mode 100644 index 00000000000..72d09f54316 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/quick_mode_3_deinit.inc @@ -0,0 +1,21 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $MASTER_1_COMMENT_2_2= $MASTER_1_COMMENT_2_2_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP +--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP +--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--connection master_1 +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/quick_mode_3_init.inc b/storage/spider/mysql-test/spider/include/quick_mode_3_init.inc new file mode 100644 index 00000000000..df7d713c4c7 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/quick_mode_3_init.inc @@ -0,0 +1,55 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $MASTER_1_COMMENT_2_2_BACKUP= $MASTER_1_COMMENT_2_2 +let $MASTER_1_COMMENT_2_2= + COMMENT='table "tbl_b", srv "s_2_2"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES +let $CHILD2_2_DROP_TABLES= + DROP TABLE IF EXISTS tbl_b; +--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES +let $CHILD2_2_CREATE_TABLES= + CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET; +--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES +let $CHILD2_2_SELECT_TABLES= + SELECT pkey FROM tbl_b ORDER BY pkey; +let $CHILD2_2_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 +--connection master_1 +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 3; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; +let $MASTER_1_SET_QUICK_PAGE_BYTE_6= + set session spider_quick_page_byte= 6; +let $MASTER_1_SET_QUICK_PAGE_BYTE_0= + set session spider_quick_page_byte= 0; diff --git a/storage/spider/mysql-test/spider/r/quick_mode_0.result b/storage/spider/mysql-test/spider/r/quick_mode_0.result new file mode 100644 index 00000000000..1cf79124b8c --- /dev/null +++ b/storage/spider/mysql-test/spider/r/quick_mode_0.result @@ -0,0 +1,515 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 +connection master_1; +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 0; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +connection child2_2; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote2; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection child2_2; +CHILD2_2_DROP_TABLES +CHILD2_2_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +DROP TABLE IF EXISTS tbl_b; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 6; + +select test 2 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 0; + +select test 3 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection child2_2; +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/quick_mode_1.result b/storage/spider/mysql-test/spider/r/quick_mode_1.result new file mode 100644 index 00000000000..1d56cff3e36 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/quick_mode_1.result @@ -0,0 +1,515 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 +connection master_1; +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 1; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +connection child2_2; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote2; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection child2_2; +CHILD2_2_DROP_TABLES +CHILD2_2_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +DROP TABLE IF EXISTS tbl_b; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 6; + +select test 2 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 0; + +select test 3 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection child2_2; +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/quick_mode_2.result b/storage/spider/mysql-test/spider/r/quick_mode_2.result new file mode 100644 index 00000000000..5b0cd75af34 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/quick_mode_2.result @@ -0,0 +1,515 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 +connection master_1; +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 2; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +connection child2_2; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote2; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection child2_2; +CHILD2_2_DROP_TABLES +CHILD2_2_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +DROP TABLE IF EXISTS tbl_b; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 6; + +select test 2 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 0; + +select test 3 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection child2_2; +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/r/quick_mode_3.result b/storage/spider/mysql-test/spider/r/quick_mode_3.result new file mode 100644 index 00000000000..4261cde2e36 --- /dev/null +++ b/storage/spider/mysql-test/spider/r/quick_mode_3.result @@ -0,0 +1,515 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 +connection master_1; +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 3; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +connection child2_2; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote2; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection child2_2; +CHILD2_2_DROP_TABLES +CHILD2_2_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +DROP TABLE IF EXISTS tbl_b; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 6; + +select test 2 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 0; + +select test 3 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection child2_2; +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/t/quick_mode_0.test b/storage/spider/mysql-test/spider/t/quick_mode_0.test new file mode 100644 index 00000000000..ffb665c0604 --- /dev/null +++ b/storage/spider/mysql-test/spider/t/quick_mode_0.test @@ -0,0 +1,309 @@ +--source ../include/quick_mode_0_init.inc +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote2; + CREATE DATABASE auto_test_remote2; + USE auto_test_remote2; +} +--enable_warnings + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_CREATE_TABLES; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_2_DROP_TABLES; + echo CHILD2_2_CREATE_TABLES; + } + --disable_warnings + eval $CHILD2_2_DROP_TABLES; + --enable_warnings + eval $CHILD2_2_CREATE_TABLES; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +DROP TABLE IF EXISTS tbl_b; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_2; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +--echo +--echo select test 1 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_6; + +--echo +--echo select test 2 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_0; + +--echo +--echo select test 3 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } + --connection child2_2 + DROP DATABASE IF EXISTS auto_test_remote2; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/quick_mode_0_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/quick_mode_1.test b/storage/spider/mysql-test/spider/t/quick_mode_1.test new file mode 100644 index 00000000000..70d61d087e3 --- /dev/null +++ b/storage/spider/mysql-test/spider/t/quick_mode_1.test @@ -0,0 +1,309 @@ +--source ../include/quick_mode_1_init.inc +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote2; + CREATE DATABASE auto_test_remote2; + USE auto_test_remote2; +} +--enable_warnings + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_CREATE_TABLES; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_2_DROP_TABLES; + echo CHILD2_2_CREATE_TABLES; + } + --disable_warnings + eval $CHILD2_2_DROP_TABLES; + --enable_warnings + eval $CHILD2_2_CREATE_TABLES; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +DROP TABLE IF EXISTS tbl_b; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_2; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +--echo +--echo select test 1 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_6; + +--echo +--echo select test 2 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_0; + +--echo +--echo select test 3 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } + --connection child2_2 + DROP DATABASE IF EXISTS auto_test_remote2; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/quick_mode_1_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/quick_mode_2.test b/storage/spider/mysql-test/spider/t/quick_mode_2.test new file mode 100644 index 00000000000..71e7b0338dc --- /dev/null +++ b/storage/spider/mysql-test/spider/t/quick_mode_2.test @@ -0,0 +1,309 @@ +--source ../include/quick_mode_2_init.inc +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote2; + CREATE DATABASE auto_test_remote2; + USE auto_test_remote2; +} +--enable_warnings + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_CREATE_TABLES; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_2_DROP_TABLES; + echo CHILD2_2_CREATE_TABLES; + } + --disable_warnings + eval $CHILD2_2_DROP_TABLES; + --enable_warnings + eval $CHILD2_2_CREATE_TABLES; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +DROP TABLE IF EXISTS tbl_b; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_2; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +--echo +--echo select test 1 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_6; + +--echo +--echo select test 2 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_0; + +--echo +--echo select test 3 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } + --connection child2_2 + DROP DATABASE IF EXISTS auto_test_remote2; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/quick_mode_2_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/t/quick_mode_3.test b/storage/spider/mysql-test/spider/t/quick_mode_3.test new file mode 100644 index 00000000000..000edd4fdff --- /dev/null +++ b/storage/spider/mysql-test/spider/t/quick_mode_3.test @@ -0,0 +1,309 @@ +--source ../include/quick_mode_3_init.inc +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote2; + CREATE DATABASE auto_test_remote2; + USE auto_test_remote2; +} +--enable_warnings + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_CREATE_TABLES; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_2_DROP_TABLES; + echo CHILD2_2_CREATE_TABLES; + } + --disable_warnings + eval $CHILD2_2_DROP_TABLES; + --enable_warnings + eval $CHILD2_2_CREATE_TABLES; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +DROP TABLE IF EXISTS tbl_b; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_2; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +--echo +--echo select test 1 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_6; + +--echo +--echo select test 2 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_0; + +--echo +--echo select test 3 +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + --connection child2_2 + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + --connection child2_2 + if ($USE_GENERAL_LOG) + { + --replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ + eval $CHILD2_2_SELECT_ARGUMENT1; + } + eval $CHILD2_2_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } + --connection child2_2 + DROP DATABASE IF EXISTS auto_test_remote2; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/quick_mode_3_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc index d48ec1f2285..ba59acd64bc 100644 --- a/storage/spider/spd_conn.cc +++ b/storage/spider/spd_conn.cc @@ -2087,6 +2087,7 @@ void spider_bg_all_conn_break( #endif if (spider->quick_targets[roop_count]) { + spider_db_free_one_quick_result((SPIDER_RESULT *) result_list->current); DBUG_ASSERT(spider->quick_targets[roop_count] == conn->quick_target); DBUG_PRINT("info", ("spider conn[%p]->quick_target=NULL", conn)); conn->quick_target = NULL; diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 1e117b68728..c2cd4beccdb 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -3473,6 +3473,22 @@ void spider_db_free_one_result( DBUG_VOID_RETURN; } +void spider_db_free_one_quick_result( + SPIDER_RESULT *result +) { + DBUG_ENTER("spider_db_free_one_quick_result"); + if (result && result->result) + { + result->result->free_result(); + if (!result->result_tmp_tbl) + { + delete result->result; + result->result = NULL; + } + } + DBUG_VOID_RETURN; +} + int spider_db_free_result( ha_spider *spider, bool final @@ -3999,11 +4015,22 @@ int spider_db_store_result( SPIDER_DB_ROW *tmp_row; uint field_count = current->result->num_fields(); SPIDER_POSITION *position; - longlong page_size = - !result_list->quick_page_size || - result_list->limit_num < result_list->quick_page_size ? - result_list->limit_num : result_list->quick_page_size; + longlong page_size; int roop_count = 0; + if (!result_list->quick_page_size) + { + if (result_list->quick_mode == 3) + { + page_size = 0; + } else { + result_list->quick_page_size = result_list->limit_num; + page_size = result_list->limit_num; + } + } else { + page_size = + result_list->limit_num < result_list->quick_page_size ? + result_list->limit_num : result_list->quick_page_size; + } current->field_count = field_count; if (!(position = (SPIDER_POSITION *) spider_bulk_malloc(spider_current_trx, 7, MYF(MY_WME | MY_ZEROFILL), @@ -4015,22 +4042,56 @@ int spider_db_store_result( current->pos_page_size = (int) page_size; current->first_position = position; current->tmp_tbl_row = tmp_row; - do { - if (!(position->row = row->clone())) + if (result_list->quick_mode == 3) + { + while (page_size > roop_count && row) { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); + if (result_list->quick_page_byte < row->get_byte_size()) + { + current->pos_page_size = roop_count; + page_size = roop_count; + result_list->quick_page_size = roop_count; + result_list->quick_page_byte = 0; + break; + } else { + result_list->quick_page_byte -= row->get_byte_size(); + } + if (!(position->row = row->clone())) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + position++; + roop_count++; + row = current->result->fetch_row(); } - position++; - roop_count++; - } while ( - page_size > roop_count && - (row = current->result->fetch_row()) - ); + } else { + do { + if (!(position->row = row->clone())) + { + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + position++; + roop_count++; + if (result_list->quick_page_byte < row->get_byte_size()) + { + current->pos_page_size = roop_count; + page_size = roop_count; + result_list->quick_page_size = roop_count; + result_list->quick_page_byte = 0; + break; + } else { + result_list->quick_page_byte -= row->get_byte_size(); + } + } while ( + page_size > roop_count && + (row = current->result->fetch_row()) + ); + } if ( result_list->quick_mode == 3 && page_size == roop_count && result_list->limit_num > roop_count && - (row = current->result->fetch_row()) + row ) { THD *thd = current_thd; char buf[MAX_FIELD_WIDTH]; @@ -4076,7 +4137,11 @@ int spider_db_store_result( result_list->record_num += roop_count; if ( result_list->internal_limit <= result_list->record_num || - page_size > roop_count + page_size > roop_count || + ( + result_list->quick_mode == 3 && + result_list->limit_num > roop_count + ) ) { DBUG_PRINT("info",("spider set finish_flg point 4")); DBUG_PRINT("info",("spider current->finish_flg = TRUE")); diff --git a/storage/spider/spd_db_conn.h b/storage/spider/spd_db_conn.h index 6ff35b794cd..bf09d672685 100644 --- a/storage/spider/spd_db_conn.h +++ b/storage/spider/spd_db_conn.h @@ -579,6 +579,10 @@ void spider_db_free_one_result( SPIDER_RESULT *result ); +void spider_db_free_one_quick_result( + SPIDER_RESULT *result +); + int spider_db_free_result( ha_spider *spider, bool final diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc index 412450b96f8..4aebc7811b4 100644 --- a/storage/spider/spd_db_handlersocket.cc +++ b/storage/spider/spd_db_handlersocket.cc @@ -359,7 +359,7 @@ spider_string *spider_db_hs_str_buffer::add( spider_db_handlersocket_row::spider_db_handlersocket_row() : spider_db_row(spider_dbton_handlersocket.dbton_id), - hs_row(NULL), field_count(0), cloned(FALSE) + hs_row(NULL), field_count(0), row_size(0), cloned(FALSE) { DBUG_ENTER("spider_db_handlersocket_row::spider_db_handlersocket_row"); DBUG_PRINT("info",("spider this=%p", this)); @@ -497,18 +497,13 @@ SPIDER_DB_ROW *spider_db_handlersocket_row::clone() { spider_db_handlersocket_row *clone_row; char *tmp_char; - uint row_size, i; + uint i; DBUG_ENTER("spider_db_handlersocket_row::clone"); DBUG_PRINT("info",("spider this=%p", this)); if (!(clone_row = new spider_db_handlersocket_row())) { DBUG_RETURN(NULL); } - row_size = 0; - for (i = 0; i < field_count; i++) - { - row_size += hs_row_first[i].size(); - } if (!spider_bulk_malloc(spider_current_trx, 169, MYF(MY_WME), &clone_row->hs_row, sizeof(SPIDER_HS_STRING_REF) * field_count, &tmp_char, row_size, @@ -525,6 +520,7 @@ SPIDER_DB_ROW *spider_db_handlersocket_row::clone() } clone_row->hs_row_first = clone_row->hs_row; clone_row->cloned = TRUE;; + clone_row->row_size = row_size;; DBUG_RETURN(NULL); } @@ -560,6 +556,13 @@ int spider_db_handlersocket_row::store_to_tmp_table( DBUG_RETURN(tmp_table->file->ha_write_row(tmp_table->record[0])); } +uint spider_db_handlersocket_row::get_byte_size() +{ + DBUG_ENTER("spider_db_handlersocket_row::get_byte_size"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(row_size); +} + spider_db_handlersocket_result_buffer::spider_db_handlersocket_result_buffer( ) : spider_db_result_buffer() @@ -676,6 +679,7 @@ SPIDER_DB_ROW *spider_db_handlersocket_result::fetch_row() } row.field_count = field_count; row.hs_row_first = row.hs_row; + row.row_size = (*hs_conn_p)->get_row_size(); DBUG_RETURN((SPIDER_DB_ROW *) &row); } @@ -694,6 +698,7 @@ SPIDER_DB_ROW *spider_db_handlersocket_result::fetch_row_from_result_buffer( } row.field_count = field_count; row.hs_row_first = row.hs_row; + row.row_size = (*hs_conn_p)->get_row_size_from_result(hs_res_buf->hs_result); DBUG_RETURN((SPIDER_DB_ROW *) &row); } @@ -729,6 +734,7 @@ SPIDER_DB_ROW *spider_db_handlersocket_result::fetch_row_from_tmp_table( } tmp_hs_row++; } + row.row_size = row_ptr - tmp_str2.ptr(); DBUG_RETURN((SPIDER_DB_ROW *) &row); } diff --git a/storage/spider/spd_db_handlersocket.h b/storage/spider/spd_db_handlersocket.h index 3767f0f3fac..075f8720abf 100644 --- a/storage/spider/spd_db_handlersocket.h +++ b/storage/spider/spd_db_handlersocket.h @@ -145,6 +145,7 @@ public: SPIDER_HS_STRING_REF *hs_row; SPIDER_HS_STRING_REF *hs_row_first; uint field_count; + uint row_size; bool cloned; spider_db_handlersocket_row(); ~spider_db_handlersocket_row(); @@ -173,6 +174,7 @@ public: TABLE *tmp_table, spider_string *str ); + uint get_byte_size(); }; class spider_db_handlersocket_result_buffer: public spider_db_result_buffer diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 7f1148655e3..cc4d2bcd3a1 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -941,6 +941,7 @@ public: TABLE *tmp_table, spider_string *str ) = 0; + virtual uint get_byte_size() = 0; }; class spider_db_result_buffer @@ -1947,6 +1948,7 @@ typedef struct st_spider_result_list int max_order; int quick_mode; longlong quick_page_size; + longlong quick_page_byte; int low_mem_read; int bulk_update_mode; int bulk_update_size; diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 8c17bc8970d..39f448e44c0 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -415,11 +415,17 @@ SPIDER_DB_ROW *spider_db_mysql_row::clone() { DBUG_RETURN(NULL); } - row_size = field_count; - for (i = 0; i < field_count; i++) + if (!record_size) { - row_size += *tmp_lengths; - tmp_lengths++; + row_size = field_count; + for (i = 0; i < field_count; i++) + { + row_size += *tmp_lengths; + tmp_lengths++; + } + record_size = row_size - field_count; + } else { + row_size = record_size + field_count; } if (!spider_bulk_malloc(spider_current_trx, 29, MYF(MY_WME), &clone_row->row, sizeof(char*) * field_count, @@ -451,6 +457,7 @@ SPIDER_DB_ROW *spider_db_mysql_row::clone() tmp_row++; } clone_row->field_count = field_count; + clone_row->record_size = record_size; clone_row->row_first = clone_row->row; clone_row->lengths_first = clone_row->lengths; clone_row->cloned = TRUE; @@ -493,6 +500,23 @@ int spider_db_mysql_row::store_to_tmp_table( DBUG_RETURN(tmp_table->file->ha_write_row(tmp_table->record[0])); } +uint spider_db_mysql_row::get_byte_size() +{ + ulong *tmp_lengths = lengths_first; + uint i; + DBUG_ENTER("spider_db_mysql_row::get_byte_size"); + DBUG_PRINT("info",("spider this=%p", this)); + if (!record_size) + { + for (i = 0; i < field_count; i++) + { + record_size += *tmp_lengths; + tmp_lengths++; + } + } + DBUG_RETURN(record_size); +} + spider_db_mysql_result::spider_db_mysql_result(SPIDER_DB_CONN *in_db_conn) : spider_db_result(in_db_conn, spider_dbton_mysql.dbton_id), db_result(NULL) @@ -559,6 +583,7 @@ SPIDER_DB_ROW *spider_db_mysql_result::fetch_row() row.field_count = mysql_num_fields(db_result); row.row_first = row.row; row.lengths_first = row.lengths; + row.record_size = 0; DBUG_RETURN((SPIDER_DB_ROW *) &row); } @@ -582,6 +607,7 @@ SPIDER_DB_ROW *spider_db_mysql_result::fetch_row_from_result_buffer( row.field_count = mysql_num_fields(db_result); row.row_first = row.row; row.lengths_first = row.lengths; + row.record_size = 0; DBUG_RETURN((SPIDER_DB_ROW *) &row); } @@ -614,6 +640,7 @@ SPIDER_DB_ROW *spider_db_mysql_result::fetch_row_from_tmp_table( row.field_count = field_count; row.row_first = row.row; row.lengths_first = row.lengths; + row.record_size = tmp_str2.length(); for (i = 0; i < field_count; i++) { if (*tmp_row) diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index 423ead89423..9a709f46c51 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -182,6 +182,7 @@ public: ulong *lengths; ulong *lengths_first; uint field_count; + uint record_size; bool cloned; spider_db_mysql_row(); ~spider_db_mysql_row(); @@ -210,6 +211,7 @@ public: TABLE *tmp_table, spider_string *str ); + uint get_byte_size(); }; class spider_db_mysql_result: public spider_db_result diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc index dfeafc58f13..e5a68f1f8c1 100644 --- a/storage/spider/spd_db_oracle.cc +++ b/storage/spider/spd_db_oracle.cc @@ -519,6 +519,7 @@ SPIDER_DB_ROW *spider_db_oracle_row::clone() clone_row->db_conn = db_conn; clone_row->result = result; clone_row->field_count = field_count; + clone_row->record_size = record_size; clone_row->access_charset = access_charset; clone_row->cloned = TRUE; if (clone_row->init()) @@ -571,6 +572,13 @@ int spider_db_oracle_row::store_to_tmp_table( DBUG_RETURN(tmp_table->file->ha_write_row(tmp_table->record[0])); } +uint spider_db_oracle_row::get_byte_size() +{ + DBUG_ENTER("spider_db_oracle_row::get_byte_size"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_RETURN(record_size); +} + int spider_db_oracle_row::init() { char *tmp_val; @@ -696,6 +704,7 @@ int spider_db_oracle_row::fetch() uint i; DBUG_ENTER("spider_db_oracle_row::fetch"); DBUG_PRINT("info",("spider this=%p", this)); + record_size = 0; for (i = 0; i < field_count; i++) { if (ind[i] == -1) @@ -757,6 +766,7 @@ int spider_db_oracle_row::fetch() } } row_size[i] = val_str[i].length(); + record_size += row_size[i]; } DBUG_RETURN(0); } @@ -911,6 +921,7 @@ SPIDER_DB_ROW *spider_db_oracle_result::fetch_row_from_tmp_table( str += row.row_size[i]; } } + row.record_size = tmp_str2.length(); DBUG_RETURN((SPIDER_DB_ROW *) &row); } diff --git a/storage/spider/spd_db_oracle.h b/storage/spider/spd_db_oracle.h index 9f9c75f0090..d0bd1757418 100644 --- a/storage/spider/spd_db_oracle.h +++ b/storage/spider/spd_db_oracle.h @@ -168,6 +168,7 @@ public: ub2 *coltp; ub2 *colsz; uint field_count; + uint record_size; ulong *row_size; ulong *row_size_first; CHARSET_INFO *access_charset; @@ -201,6 +202,7 @@ public: TABLE *tmp_table, spider_string *str ); + uint get_byte_size(); /* for oracle */ int init(); void deinit(); diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 38ded445d44..23bbff22fbb 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -960,6 +960,7 @@ typedef struct st_spider_share longlong priority; int quick_mode; longlong quick_page_size; + longlong quick_page_byte; int low_mem_read; int table_count_mode; int select_column_mode; diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc index a90f628603e..c10ed3aad80 100644 --- a/storage/spider/spd_param.cc +++ b/storage/spider/spd_param.cc @@ -1362,6 +1362,31 @@ longlong spider_param_quick_page_size( quick_page_size : THDVAR(thd, quick_page_size)); } +/* + -1 :use table parameter + 0-:the limitation of memory size + */ +static MYSQL_THDVAR_LONGLONG( + quick_page_byte, /* name */ + PLUGIN_VAR_RQCMDARG, /* opt */ + "The limitation of memory size in a page when acquisition one by one", /* comment */ + NULL, /* check */ + NULL, /* update */ + -1, /* def */ + -1, /* min */ + 9223372036854775807LL, /* max */ + 0 /* blk */ +); + +longlong spider_param_quick_page_byte( + THD *thd, + longlong quick_page_byte +) { + DBUG_ENTER("spider_param_quick_page_byte"); + DBUG_RETURN(THDVAR(thd, quick_page_byte) < 0 ? + quick_page_byte : THDVAR(thd, quick_page_byte)); +} + /* -1 :use table parameter 0 :It doesn't use low memory mode. @@ -3354,6 +3379,7 @@ static struct st_mysql_sys_var* spider_system_variables[] = { MYSQL_SYSVAR(net_write_timeout), MYSQL_SYSVAR(quick_mode), MYSQL_SYSVAR(quick_page_size), + MYSQL_SYSVAR(quick_page_byte), MYSQL_SYSVAR(low_mem_read), MYSQL_SYSVAR(select_column_mode), #ifndef WITHOUT_SPIDER_BG_SEARCH diff --git a/storage/spider/spd_param.h b/storage/spider/spd_param.h index e615fc672d4..7919b0c4837 100644 --- a/storage/spider/spd_param.h +++ b/storage/spider/spd_param.h @@ -171,6 +171,10 @@ longlong spider_param_quick_page_size( THD *thd, longlong quick_page_size ); +longlong spider_param_quick_page_byte( + THD *thd, + longlong quick_page_byte +); int spider_param_low_mem_read( THD *thd, int low_mem_read diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 1f220b193e5..fe5265184b6 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -2045,6 +2045,7 @@ int spider_parse_connect_info( share->priority = -1; share->quick_mode = -1; share->quick_page_size = -1; + share->quick_page_byte = -1; share->low_mem_read = -1; share->table_count_mode = -1; share->select_column_mode = -1; @@ -2290,6 +2291,7 @@ int spider_parse_connect_info( SPIDER_PARAM_INT_WITH_MAX("qch", query_cache, 0, 2); SPIDER_PARAM_INT_WITH_MAX("qcs", query_cache_sync, 0, 3); SPIDER_PARAM_INT_WITH_MAX("qmd", quick_mode, 0, 3); + SPIDER_PARAM_LONGLONG("qpb", quick_page_byte, 0); SPIDER_PARAM_LONGLONG("qps", quick_page_size, 0); SPIDER_PARAM_INT_WITH_MAX("rom", read_only_mode, 0, 1); SPIDER_PARAM_DOUBLE("rrt", read_rate, 0); @@ -2459,6 +2461,7 @@ int spider_parse_connect_info( SPIDER_PARAM_LONGLONG("internal_offset", internal_offset, 0); SPIDER_PARAM_INT_WITH_MAX("reset_sql_alloc", reset_sql_alloc, 0, 1); SPIDER_PARAM_INT_WITH_MAX("semi_table_lock", semi_table_lock, 0, 1); + SPIDER_PARAM_LONGLONG("quick_page_byte", quick_page_byte, 0); SPIDER_PARAM_LONGLONG("quick_page_size", quick_page_size, 0); #ifndef WITHOUT_SPIDER_BG_SEARCH SPIDER_PARAM_LONGLONG("bgs_second_read", bgs_second_read, 0); @@ -3824,9 +3827,11 @@ int spider_set_connect_info_default( if (share->priority == -1) share->priority = 1000000; if (share->quick_mode == -1) - share->quick_mode = 0; + share->quick_mode = 3; if (share->quick_page_size == -1) - share->quick_page_size = 100; + share->quick_page_size = 1024; + if (share->quick_page_byte == -1) + share->quick_page_byte = 10485760; if (share->low_mem_read == -1) share->low_mem_read = 1; if (share->table_count_mode == -1) @@ -7997,6 +8002,8 @@ void spider_set_result_list_param( spider_param_quick_mode(thd, share->quick_mode); result_list->quick_page_size = spider_param_quick_page_size(thd, share->quick_page_size); + result_list->quick_page_byte = + spider_param_quick_page_byte(thd, share->quick_page_byte); result_list->low_mem_read = spider_param_low_mem_read(thd, share->low_mem_read); DBUG_VOID_RETURN; From 6d80d35d9161287e6e72ac728338473c96f9fb22 Mon Sep 17 00:00:00 2001 From: Kentoku Date: Thu, 13 Dec 2018 03:11:57 +0900 Subject: [PATCH 12/91] MDEV-16787 optimistic parallel replication fails on spider Add a system variable spider_slave_trx_isolation. - spider_slave_trx_isolation The transaction isolation level when Spider table is used by slave SQL thread. -1 : OFF 0 : READ UNCOMMITTED 1 : READ COMMITTED 2 : REPEATABLE READ 3 : SERIALIZABLE The default value is -1 Miscellaneous Spider typos --- .../include/slave_trx_isolation_deinit.inc | 17 ++ .../include/slave_trx_isolation_init.inc | 39 ++++ .../spider/r/slave_trx_isolation.result | 110 ++++++++++++ .../spider/t/slave_trx_isolation.test | 166 ++++++++++++++++++ storage/spider/spd_db_mysql.cc | 2 +- storage/spider/spd_db_oracle.cc | 2 +- storage/spider/spd_group_by_handler.cc | 4 +- storage/spider/spd_param.cc | 28 +++ storage/spider/spd_param.h | 1 + storage/spider/spd_trx.cc | 24 +-- 10 files changed, 378 insertions(+), 15 deletions(-) create mode 100644 storage/spider/mysql-test/spider/include/slave_trx_isolation_deinit.inc create mode 100644 storage/spider/mysql-test/spider/include/slave_trx_isolation_init.inc create mode 100644 storage/spider/mysql-test/spider/r/slave_trx_isolation.result create mode 100644 storage/spider/mysql-test/spider/t/slave_trx_isolation.test diff --git a/storage/spider/mysql-test/spider/include/slave_trx_isolation_deinit.inc b/storage/spider/mysql-test/spider/include/slave_trx_isolation_deinit.inc new file mode 100644 index 00000000000..e5f585e5cca --- /dev/null +++ b/storage/spider/mysql-test/spider/include/slave_trx_isolation_deinit.inc @@ -0,0 +1,17 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP +--let $USE_GENERAL_LOG= $USE_GENERAL_LOG_BACKUP +--connection slave1_1 +set global spider_slave_trx_isolation= @old_spider_slave_trx_isolation; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../include/deinit_spider.inc +--source ../t/slave_test_deinit.inc +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/include/slave_trx_isolation_init.inc b/storage/spider/mysql-test/spider/include/slave_trx_isolation_init.inc new file mode 100644 index 00000000000..94ccf1d3295 --- /dev/null +++ b/storage/spider/mysql-test/spider/include/slave_trx_isolation_init.inc @@ -0,0 +1,39 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--source ../t/slave_test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'; +--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2 +--let $OUTPUT_CHILD_GROUP2= 1 +--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG +--let $USE_GENERAL_LOG= 1 +--connection slave1_1 +--disable_warnings +--disable_query_log +--disable_result_log +--source ../include/init_spider.inc +--enable_result_log +--enable_query_log +--enable_warnings +set @old_spider_slave_trx_isolation= @@spider_slave_trx_isolation; +set global spider_slave_trx_isolation= 1; diff --git a/storage/spider/mysql-test/spider/r/slave_trx_isolation.result b/storage/spider/mysql-test/spider/r/slave_trx_isolation.result new file mode 100644 index 00000000000..167739beaad --- /dev/null +++ b/storage/spider/mysql-test/spider/r/slave_trx_isolation.result @@ -0,0 +1,110 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 +for slave1_1 +connection slave1_1; +set @old_spider_slave_trx_isolation= @@spider_slave_trx_isolation; +set global spider_slave_trx_isolation= 1; + +drop and create databases +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection slave1_1; +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +DROP DATABASE IF EXISTS auto_test_remote; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +create table and insert +connection child2_1; +CHILD2_1_DROP_TABLES +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +connection slave1_1; +connection master_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE2 MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +connection master_1; +SET SESSION sql_log_bin= 1; +connection slave1_1; +DROP TABLE IF EXISTS tbl_a; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +connection master_1; +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +connection slave1_1; +connection master_1; +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'; +argument +set session time_zone = '+00:00' +SET NAMES utf8 +set session transaction isolation level read committed;set session autocommit = 1;start transaction +SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +connection slave1_1; +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection slave1_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection slave1_1; +set global spider_slave_trx_isolation= @old_spider_slave_trx_isolation; +for slave1_1 +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +child3_1 +child3_2 +child3_3 + +end of test diff --git a/storage/spider/mysql-test/spider/t/slave_trx_isolation.test b/storage/spider/mysql-test/spider/t/slave_trx_isolation.test new file mode 100644 index 00000000000..d1dea8546b9 --- /dev/null +++ b/storage/spider/mysql-test/spider/t/slave_trx_isolation.test @@ -0,0 +1,166 @@ +--source ../include/slave_trx_isolation_init.inc +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +DROP DATABASE IF EXISTS auto_test_local; +CREATE DATABASE auto_test_local; +USE auto_test_local; +if ($USE_REPLICATION) +{ + --connection slave1_1 + DROP DATABASE IF EXISTS auto_test_local; + CREATE DATABASE auto_test_local; + USE auto_test_local; +} +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + if ($USE_GENERAL_LOG) + { + SET @old_log_output = @@global.log_output; + SET GLOBAL log_output = 'TABLE,FILE'; + } + DROP DATABASE IF EXISTS auto_test_remote; + CREATE DATABASE auto_test_remote; + USE auto_test_remote; +} +--enable_warnings + +--echo +--echo create table and insert +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($OUTPUT_CHILD_GROUP2) + { + --disable_query_log + echo CHILD2_1_DROP_TABLES; + echo CHILD2_1_CREATE_TABLES; + } + --disable_warnings + eval $CHILD2_1_DROP_TABLES; + --enable_warnings + eval $CHILD2_1_CREATE_TABLES; + if ($OUTPUT_CHILD_GROUP2) + { + --enable_query_log + } + if ($USE_GENERAL_LOG) + { + TRUNCATE TABLE mysql.general_log; + } + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +--connection master_1 +if ($USE_REPLICATION) +{ + save_master_pos; + --connection slave1_1 + sync_with_master; + --connection master_1 + --disable_query_log + SET SESSION sql_log_bin= 0; + --enable_query_log +} +--disable_warnings +DROP TABLE IF EXISTS tbl_a; +--enable_warnings +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE2 MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE2 $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log +--connection master_1 +if ($USE_REPLICATION) +{ + SET SESSION sql_log_bin= 1; + --connection slave1_1 + --disable_warnings + DROP TABLE IF EXISTS tbl_a; + --enable_warnings + --disable_query_log + echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; + eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; + --enable_query_log + --connection master_1 +} +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +if ($USE_REPLICATION) +{ + save_master_pos; + --connection slave1_1 + sync_with_master; + --connection master_1 + --disable_query_log + SET SESSION sql_log_bin= 0; + --enable_query_log +} +if ($USE_CHILD_GROUP2) +{ + if (!$OUTPUT_CHILD_GROUP2) + { + --disable_query_log + --disable_result_log + } + --connection child2_1 + if ($USE_GENERAL_LOG) + { + eval $CHILD2_1_SELECT_ARGUMENT1; + } + eval $CHILD2_1_SELECT_TABLES; + if (!$OUTPUT_CHILD_GROUP2) + { + --enable_query_log + --enable_result_log + } +} +if ($USE_REPLICATION) +{ + --connection slave1_1 + SELECT pkey FROM tbl_a ORDER BY pkey; +} + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; +if ($USE_REPLICATION) +{ + --connection slave1_1 + DROP DATABASE IF EXISTS auto_test_local; +} +if ($USE_CHILD_GROUP2) +{ + --connection child2_1 + DROP DATABASE IF EXISTS auto_test_remote; + if ($USE_GENERAL_LOG) + { + SET GLOBAL log_output = @old_log_output; + } +} +--enable_warnings +--source ../include/slave_trx_isolation_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index 39f448e44c0..ceb38f886aa 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -5895,7 +5895,7 @@ int spider_mysql_share::convert_key_hint_str() DBUG_ENTER("spider_mysql_share::convert_key_hint_str"); if (spider_share->access_charset->cset != system_charset_info->cset) { - /* need convertion */ + /* need conversion */ for (roop_count = 0, tmp_key_hint = key_hint; roop_count < (int) table_share->keys; roop_count++, tmp_key_hint++) { diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc index e5a68f1f8c1..82a1e9a0fbc 100644 --- a/storage/spider/spd_db_oracle.cc +++ b/storage/spider/spd_db_oracle.cc @@ -4816,7 +4816,7 @@ int spider_oracle_share::convert_key_hint_str() DBUG_ENTER("spider_oracle_share::convert_key_hint_str"); if (spider_share->access_charset->cset != system_charset_info->cset) { - /* need convertion */ + /* need conversion */ for (roop_count = 0, tmp_key_hint = key_hint; roop_count < (int) table_share->keys; roop_count++, tmp_key_hint++) { diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc index 86a9f8cba68..3b57092c4ce 100644 --- a/storage/spider/spd_group_by_handler.cc +++ b/storage/spider/spd_group_by_handler.cc @@ -822,7 +822,7 @@ void spider_fields::choose_a_conn( current_conn_holder = first_conn_holder; } - DBUG_PRINT("info",("spider choosed connection is %p", + DBUG_PRINT("info",("spider chosen connection is %p", current_conn_holder->conn)); last_conn_holder = current_conn_holder; current_conn_holder = current_conn_holder->next; @@ -2065,7 +2065,7 @@ group_by_handler *spider_create_group_by_handler( fields->check_support_dbton(dbton_bitmap); if (!fields->has_conn_holder()) { - DBUG_PRINT("info",("spider all choosed connections can't match dbton_id")); + DBUG_PRINT("info",("spider all chosen connections can't match dbton_id")); delete fields; DBUG_RETURN(NULL); } diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc index c10ed3aad80..6b237bbfff8 100644 --- a/storage/spider/spd_param.cc +++ b/storage/spider/spd_param.cc @@ -3328,6 +3328,33 @@ uint spider_param_table_crd_thread_count() } #endif +static int spider_slave_trx_isolation; +/* + -1 :off + 0 :read uncommitted + 1 :read committed + 2 :repeatable read + 3 :serializable + */ +static MYSQL_SYSVAR_INT( + slave_trx_isolation, + spider_slave_trx_isolation, + PLUGIN_VAR_RQCMDARG, + "Transaction isolation level when Spider table is used by slave SQL thread", + NULL, /* check */ + NULL, /* update */ + -1, /* def */ + -1, /* min */ + 3, /* max */ + 0 /* blk */ +); + +int spider_param_slave_trx_isolation() +{ + DBUG_ENTER("spider_param_slave_trx_isolation"); + DBUG_RETURN(spider_slave_trx_isolation); +} + static struct st_mysql_storage_engine spider_storage_engine = { MYSQL_HANDLERTON_INTERFACE_VERSION }; @@ -3477,6 +3504,7 @@ static struct st_mysql_sys_var* spider_system_variables[] = { MYSQL_SYSVAR(table_sts_thread_count), MYSQL_SYSVAR(table_crd_thread_count), #endif + MYSQL_SYSVAR(slave_trx_isolation), NULL }; diff --git a/storage/spider/spd_param.h b/storage/spider/spd_param.h index 7919b0c4837..8fdf2e452b2 100644 --- a/storage/spider/spd_param.h +++ b/storage/spider/spd_param.h @@ -420,3 +420,4 @@ int spider_param_load_crd_at_startup( uint spider_param_table_sts_thread_count(); uint spider_param_table_crd_thread_count(); #endif +int spider_param_slave_trx_isolation(); diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc index 565665dc6f7..6204ca9852c 100644 --- a/storage/spider/spd_trx.cc +++ b/storage/spider/spd_trx.cc @@ -1586,21 +1586,23 @@ int spider_check_and_set_trx_isolation( SPIDER_CONN *conn, int *need_mon ) { + THD *thd = conn->thd; int trx_isolation; DBUG_ENTER("spider_check_and_set_trx_isolation"); - - trx_isolation = thd_tx_isolation(conn->thd); - DBUG_PRINT("info",("spider local trx_isolation=%d", trx_isolation)); -/* - DBUG_PRINT("info",("spider conn->trx_isolation=%d", conn->trx_isolation)); - if (conn->trx_isolation != trx_isolation) + if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL) { -*/ - spider_conn_queue_trx_isolation(conn, trx_isolation); -/* - conn->trx_isolation = trx_isolation; + if ((trx_isolation = spider_param_slave_trx_isolation()) == -1) + { + trx_isolation = thd_tx_isolation(thd); + DBUG_PRINT("info",("spider local trx_isolation=%d", trx_isolation)); + } else { + DBUG_PRINT("info",("spider slave trx_isolation=%d", trx_isolation)); + } + } else { + trx_isolation = thd_tx_isolation(thd); + DBUG_PRINT("info",("spider local trx_isolation=%d", trx_isolation)); } -*/ + spider_conn_queue_trx_isolation(conn, trx_isolation); DBUG_RETURN(0); } From be556f817b88139502dd75cdbf22a28c2fe5806c Mon Sep 17 00:00:00 2001 From: Kentoku Date: Mon, 24 Dec 2018 23:40:33 +0900 Subject: [PATCH 13/91] remove unnecessary drop database/table from quick_mode.test add simplified quick_mode.test --- .../bugfix/include/quick_mode_0_deinit.inc | 19 + .../bugfix/include/quick_mode_0_init.inc | 51 ++ .../bugfix/include/quick_mode_1_deinit.inc | 19 + .../bugfix/include/quick_mode_1_init.inc | 51 ++ .../bugfix/include/quick_mode_2_deinit.inc | 19 + .../bugfix/include/quick_mode_2_init.inc | 51 ++ .../bugfix/include/quick_mode_3_deinit.inc | 19 + .../bugfix/include/quick_mode_3_init.inc | 51 ++ .../spider/bugfix/r/quick_mode_0.result | 504 ++++++++++++++++++ .../spider/bugfix/r/quick_mode_1.result | 504 ++++++++++++++++++ .../spider/bugfix/r/quick_mode_2.result | 504 ++++++++++++++++++ .../spider/bugfix/r/quick_mode_3.result | 504 ++++++++++++++++++ .../spider/bugfix/t/quick_mode_0.cnf | 4 + .../spider/bugfix/t/quick_mode_0.test | 156 ++++++ .../spider/bugfix/t/quick_mode_1.cnf | 4 + .../spider/bugfix/t/quick_mode_1.test | 156 ++++++ .../spider/bugfix/t/quick_mode_2.cnf | 4 + .../spider/bugfix/t/quick_mode_2.test | 156 ++++++ .../spider/bugfix/t/quick_mode_3.cnf | 4 + .../spider/bugfix/t/quick_mode_3.test | 157 ++++++ .../mysql-test/spider/r/quick_mode_0.result | 7 - .../mysql-test/spider/r/quick_mode_1.result | 7 - .../mysql-test/spider/r/quick_mode_2.result | 7 - .../mysql-test/spider/r/quick_mode_3.result | 7 - .../mysql-test/spider/t/quick_mode_0.test | 15 - .../mysql-test/spider/t/quick_mode_1.test | 15 - .../mysql-test/spider/t/quick_mode_2.test | 15 - .../mysql-test/spider/t/quick_mode_3.test | 15 - 28 files changed, 2937 insertions(+), 88 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/include/quick_mode_0_deinit.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/quick_mode_0_init.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/quick_mode_1_deinit.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/quick_mode_1_init.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/quick_mode_2_deinit.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/quick_mode_2_init.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/quick_mode_3_deinit.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/quick_mode_3_init.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/r/quick_mode_0.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/quick_mode_1.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/quick_mode_2.result create mode 100644 storage/spider/mysql-test/spider/bugfix/r/quick_mode_3.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/quick_mode_0.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/quick_mode_0.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/quick_mode_1.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/quick_mode_1.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/quick_mode_2.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/quick_mode_2.test create mode 100644 storage/spider/mysql-test/spider/bugfix/t/quick_mode_3.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/quick_mode_3.test diff --git a/storage/spider/mysql-test/spider/bugfix/include/quick_mode_0_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_0_deinit.inc new file mode 100644 index 00000000000..42124a794ea --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_0_deinit.inc @@ -0,0 +1,19 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $MASTER_1_COMMENT_2_2= $MASTER_1_COMMENT_2_2_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP +--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP +--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP +--connection master_1 +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/quick_mode_0_init.inc b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_0_init.inc new file mode 100644 index 00000000000..2656517216c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_0_init.inc @@ -0,0 +1,51 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $MASTER_1_COMMENT_2_2_BACKUP= $MASTER_1_COMMENT_2_2 +let $MASTER_1_COMMENT_2_2= + COMMENT='table "tbl_b", srv "s_2_2"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES +let $CHILD2_2_DROP_TABLES= + DROP TABLE IF EXISTS tbl_b; +--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES +let $CHILD2_2_CREATE_TABLES= + CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET; +--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES +let $CHILD2_2_SELECT_TABLES= + SELECT pkey FROM tbl_b ORDER BY pkey; +let $CHILD2_2_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--connection master_1 +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 0; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; +let $MASTER_1_SET_QUICK_PAGE_BYTE_6= + set session spider_quick_page_byte= 6; +let $MASTER_1_SET_QUICK_PAGE_BYTE_0= + set session spider_quick_page_byte= 0; diff --git a/storage/spider/mysql-test/spider/bugfix/include/quick_mode_1_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_1_deinit.inc new file mode 100644 index 00000000000..42124a794ea --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_1_deinit.inc @@ -0,0 +1,19 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $MASTER_1_COMMENT_2_2= $MASTER_1_COMMENT_2_2_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP +--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP +--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP +--connection master_1 +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/quick_mode_1_init.inc b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_1_init.inc new file mode 100644 index 00000000000..9a8de407569 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_1_init.inc @@ -0,0 +1,51 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $MASTER_1_COMMENT_2_2_BACKUP= $MASTER_1_COMMENT_2_2 +let $MASTER_1_COMMENT_2_2= + COMMENT='table "tbl_b", srv "s_2_2"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES +let $CHILD2_2_DROP_TABLES= + DROP TABLE IF EXISTS tbl_b; +--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES +let $CHILD2_2_CREATE_TABLES= + CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET; +--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES +let $CHILD2_2_SELECT_TABLES= + SELECT pkey FROM tbl_b ORDER BY pkey; +let $CHILD2_2_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--connection master_1 +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 1; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; +let $MASTER_1_SET_QUICK_PAGE_BYTE_6= + set session spider_quick_page_byte= 6; +let $MASTER_1_SET_QUICK_PAGE_BYTE_0= + set session spider_quick_page_byte= 0; diff --git a/storage/spider/mysql-test/spider/bugfix/include/quick_mode_2_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_2_deinit.inc new file mode 100644 index 00000000000..42124a794ea --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_2_deinit.inc @@ -0,0 +1,19 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $MASTER_1_COMMENT_2_2= $MASTER_1_COMMENT_2_2_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP +--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP +--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP +--connection master_1 +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/quick_mode_2_init.inc b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_2_init.inc new file mode 100644 index 00000000000..dbe3f703a2f --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_2_init.inc @@ -0,0 +1,51 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $MASTER_1_COMMENT_2_2_BACKUP= $MASTER_1_COMMENT_2_2 +let $MASTER_1_COMMENT_2_2= + COMMENT='table "tbl_b", srv "s_2_2"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES +let $CHILD2_2_DROP_TABLES= + DROP TABLE IF EXISTS tbl_b; +--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES +let $CHILD2_2_CREATE_TABLES= + CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET; +--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES +let $CHILD2_2_SELECT_TABLES= + SELECT pkey FROM tbl_b ORDER BY pkey; +let $CHILD2_2_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--connection master_1 +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 2; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; +let $MASTER_1_SET_QUICK_PAGE_BYTE_6= + set session spider_quick_page_byte= 6; +let $MASTER_1_SET_QUICK_PAGE_BYTE_0= + set session spider_quick_page_byte= 0; diff --git a/storage/spider/mysql-test/spider/bugfix/include/quick_mode_3_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_3_deinit.inc new file mode 100644 index 00000000000..42124a794ea --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_3_deinit.inc @@ -0,0 +1,19 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $MASTER_1_COMMENT_2_2= $MASTER_1_COMMENT_2_2_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP +--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP +--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP +--connection master_1 +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/quick_mode_3_init.inc b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_3_init.inc new file mode 100644 index 00000000000..81239206dfc --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/quick_mode_3_init.inc @@ -0,0 +1,51 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $MASTER_1_COMMENT_2_2_BACKUP= $MASTER_1_COMMENT_2_2 +let $MASTER_1_COMMENT_2_2= + COMMENT='table "tbl_b", srv "s_2_2"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES +let $CHILD2_2_DROP_TABLES= + DROP TABLE IF EXISTS tbl_b; +--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES +let $CHILD2_2_CREATE_TABLES= + CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET; +--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES +let $CHILD2_2_SELECT_TABLES= + SELECT pkey FROM tbl_b ORDER BY pkey; +let $CHILD2_2_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +--connection master_1 +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 3; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; +let $MASTER_1_SET_QUICK_PAGE_BYTE_6= + set session spider_quick_page_byte= 6; +let $MASTER_1_SET_QUICK_PAGE_BYTE_0= + set session spider_quick_page_byte= 0; diff --git a/storage/spider/mysql-test/spider/bugfix/r/quick_mode_0.result b/storage/spider/mysql-test/spider/bugfix/r/quick_mode_0.result new file mode 100644 index 00000000000..6e5a0052370 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/quick_mode_0.result @@ -0,0 +1,504 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection master_1; +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 0; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; + +this test is for MDEV-16520 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +connection child2_2; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection child2_2; +CHILD2_2_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 6; + +select test 2 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 0; + +select test 3 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection child2_2; +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/r/quick_mode_1.result b/storage/spider/mysql-test/spider/bugfix/r/quick_mode_1.result new file mode 100644 index 00000000000..bca6d172a49 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/quick_mode_1.result @@ -0,0 +1,504 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection master_1; +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 1; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; + +this test is for MDEV-16520 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +connection child2_2; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection child2_2; +CHILD2_2_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 6; + +select test 2 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 0; + +select test 3 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection child2_2; +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/r/quick_mode_2.result b/storage/spider/mysql-test/spider/bugfix/r/quick_mode_2.result new file mode 100644 index 00000000000..61a7764dddb --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/quick_mode_2.result @@ -0,0 +1,504 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection master_1; +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 2; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; + +this test is for MDEV-16520 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +connection child2_2; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection child2_2; +CHILD2_2_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 6; + +select test 2 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 0; + +select test 3 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection child2_2; +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/r/quick_mode_3.result b/storage/spider/mysql-test/spider/bugfix/r/quick_mode_3.result new file mode 100644 index 00000000000..38387a45509 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/quick_mode_3.result @@ -0,0 +1,504 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +connection master_1; +set @old_spider_quick_mode= @@spider_quick_mode; +set session spider_quick_mode= 3; +set @old_spider_quick_page_size= @@spider_quick_page_size; +set session spider_quick_page_size= 3; +set @old_spider_quick_page_byte= @@spider_quick_page_byte; + +this test is for MDEV-16520 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +connection child2_2; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection child2_2; +CHILD2_2_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +CREATE TABLE tbl_b ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +select test 1 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 6; + +select test 2 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection master_1; +set session spider_quick_page_byte= 0; + +select test 3 +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection child2_2; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote`.`tbl_a` order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +connection child2_2; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 0 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 1 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 2 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 3 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 4 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 5 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 6 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 7 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 8 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 9 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 10 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 11 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 12 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 13 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 14 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 15 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 16 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 17 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 18 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 19 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 20 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 21 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 22 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 23 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 24 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 25 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 26 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 27 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 28 +select `pkey` from `auto_test_remote2`.`tbl_b` where `pkey` = 29 +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_b ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection child2_2; +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; +connection master_1; +set session spider_quick_mode= @old_spider_quick_mode; +set session spider_quick_page_size= @old_spider_quick_page_size; +set session spider_quick_page_byte= @old_spider_quick_page_byte; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/quick_mode_0.cnf b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_0.cnf new file mode 100644 index 00000000000..e0ffb99c38e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_0.cnf @@ -0,0 +1,4 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf +!include ../my_2_2.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/quick_mode_0.test b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_0.test new file mode 100644 index 00000000000..235edc10d12 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_0.test @@ -0,0 +1,156 @@ +--source ../include/quick_mode_0_init.inc +--echo +--echo this test is for MDEV-16520 +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +--connection child2_2 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +--disable_query_log +echo CHILD2_2_CREATE_TABLES; +eval $CHILD2_2_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_2; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +--echo +--echo select test 1 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_6; + +--echo +--echo select test 2 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_0; + +--echo +--echo select test 3 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--connection child2_2 +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/quick_mode_0_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/quick_mode_1.cnf b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_1.cnf new file mode 100644 index 00000000000..e0ffb99c38e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_1.cnf @@ -0,0 +1,4 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf +!include ../my_2_2.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/quick_mode_1.test b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_1.test new file mode 100644 index 00000000000..01fa0cb5128 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_1.test @@ -0,0 +1,156 @@ +--source ../include/quick_mode_1_init.inc +--echo +--echo this test is for MDEV-16520 +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +--connection child2_2 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +--disable_query_log +echo CHILD2_2_CREATE_TABLES; +eval $CHILD2_2_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_2; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +--echo +--echo select test 1 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_6; + +--echo +--echo select test 2 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_0; + +--echo +--echo select test 3 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--connection child2_2 +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/quick_mode_1_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/quick_mode_2.cnf b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_2.cnf new file mode 100644 index 00000000000..e0ffb99c38e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_2.cnf @@ -0,0 +1,4 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf +!include ../my_2_2.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/quick_mode_2.test b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_2.test new file mode 100644 index 00000000000..3ea8138e755 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_2.test @@ -0,0 +1,156 @@ +--source ../include/quick_mode_2_init.inc +--echo +--echo this test is for MDEV-16520 +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +--connection child2_2 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +--disable_query_log +echo CHILD2_2_CREATE_TABLES; +eval $CHILD2_2_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_2; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +--echo +--echo select test 1 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_6; + +--echo +--echo select test 2 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_0; + +--echo +--echo select test 3 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--connection child2_2 +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/quick_mode_2_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/quick_mode_3.cnf b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_3.cnf new file mode 100644 index 00000000000..e0ffb99c38e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_3.cnf @@ -0,0 +1,4 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf +!include ../my_2_2.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/quick_mode_3.test b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_3.test new file mode 100644 index 00000000000..bc926b0a296 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/quick_mode_3.test @@ -0,0 +1,157 @@ +--source ../include/quick_mode_3_init.inc +--echo +--echo this test is for MDEV-16520 +--echo +--echo drop and create databases + +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +--connection child2_2 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote2; +USE auto_test_remote2; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +--disable_query_log +echo CHILD2_2_CREATE_TABLES; +eval $CHILD2_2_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +echo CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_2; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_b ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_2; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); +INSERT INTO tbl_b (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +INSERT INTO tbl_b (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19); +INSERT INTO tbl_b (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29); + +--echo +--echo select test 1 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_6; + +--echo +--echo select test 2 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--connection master_1 +eval $MASTER_1_SET_QUICK_PAGE_BYTE_0; + +--echo +--echo select test 3 + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection child2_2 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT a.pkey FROM tbl_a a, tbl_b b WHERE a.pkey = b.pkey; + +--connection child2_1 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection child2_2 +--replace_regex /tmp_spider_bka_0x[0-9a-f]*/tmp_spider_bka_xxxx/ +eval $CHILD2_2_SELECT_ARGUMENT1; +eval $CHILD2_2_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--connection child2_2 +DROP DATABASE IF EXISTS auto_test_remote2; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/quick_mode_3_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/r/quick_mode_0.result b/storage/spider/mysql-test/spider/r/quick_mode_0.result index 1cf79124b8c..239c3ee1175 100644 --- a/storage/spider/mysql-test/spider/r/quick_mode_0.result +++ b/storage/spider/mysql-test/spider/r/quick_mode_0.result @@ -16,34 +16,27 @@ set @old_spider_quick_page_byte= @@spider_quick_page_byte; drop and create databases connection master_1; -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; connection child2_1; SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; -DROP DATABASE IF EXISTS auto_test_remote; CREATE DATABASE auto_test_remote; USE auto_test_remote; connection child2_2; SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; -DROP DATABASE IF EXISTS auto_test_remote2; CREATE DATABASE auto_test_remote2; USE auto_test_remote2; create table and insert connection child2_1; -CHILD2_1_DROP_TABLES CHILD2_1_CREATE_TABLES TRUNCATE TABLE mysql.general_log; connection child2_2; -CHILD2_2_DROP_TABLES CHILD2_2_CREATE_TABLES TRUNCATE TABLE mysql.general_log; connection master_1; -DROP TABLE IF EXISTS tbl_a; -DROP TABLE IF EXISTS tbl_b; CREATE TABLE tbl_a ( pkey int NOT NULL, PRIMARY KEY (pkey) diff --git a/storage/spider/mysql-test/spider/r/quick_mode_1.result b/storage/spider/mysql-test/spider/r/quick_mode_1.result index 1d56cff3e36..d0db0729c39 100644 --- a/storage/spider/mysql-test/spider/r/quick_mode_1.result +++ b/storage/spider/mysql-test/spider/r/quick_mode_1.result @@ -16,34 +16,27 @@ set @old_spider_quick_page_byte= @@spider_quick_page_byte; drop and create databases connection master_1; -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; connection child2_1; SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; -DROP DATABASE IF EXISTS auto_test_remote; CREATE DATABASE auto_test_remote; USE auto_test_remote; connection child2_2; SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; -DROP DATABASE IF EXISTS auto_test_remote2; CREATE DATABASE auto_test_remote2; USE auto_test_remote2; create table and insert connection child2_1; -CHILD2_1_DROP_TABLES CHILD2_1_CREATE_TABLES TRUNCATE TABLE mysql.general_log; connection child2_2; -CHILD2_2_DROP_TABLES CHILD2_2_CREATE_TABLES TRUNCATE TABLE mysql.general_log; connection master_1; -DROP TABLE IF EXISTS tbl_a; -DROP TABLE IF EXISTS tbl_b; CREATE TABLE tbl_a ( pkey int NOT NULL, PRIMARY KEY (pkey) diff --git a/storage/spider/mysql-test/spider/r/quick_mode_2.result b/storage/spider/mysql-test/spider/r/quick_mode_2.result index 5b0cd75af34..538057e3cda 100644 --- a/storage/spider/mysql-test/spider/r/quick_mode_2.result +++ b/storage/spider/mysql-test/spider/r/quick_mode_2.result @@ -16,34 +16,27 @@ set @old_spider_quick_page_byte= @@spider_quick_page_byte; drop and create databases connection master_1; -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; connection child2_1; SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; -DROP DATABASE IF EXISTS auto_test_remote; CREATE DATABASE auto_test_remote; USE auto_test_remote; connection child2_2; SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; -DROP DATABASE IF EXISTS auto_test_remote2; CREATE DATABASE auto_test_remote2; USE auto_test_remote2; create table and insert connection child2_1; -CHILD2_1_DROP_TABLES CHILD2_1_CREATE_TABLES TRUNCATE TABLE mysql.general_log; connection child2_2; -CHILD2_2_DROP_TABLES CHILD2_2_CREATE_TABLES TRUNCATE TABLE mysql.general_log; connection master_1; -DROP TABLE IF EXISTS tbl_a; -DROP TABLE IF EXISTS tbl_b; CREATE TABLE tbl_a ( pkey int NOT NULL, PRIMARY KEY (pkey) diff --git a/storage/spider/mysql-test/spider/r/quick_mode_3.result b/storage/spider/mysql-test/spider/r/quick_mode_3.result index 4261cde2e36..9232dd152de 100644 --- a/storage/spider/mysql-test/spider/r/quick_mode_3.result +++ b/storage/spider/mysql-test/spider/r/quick_mode_3.result @@ -16,34 +16,27 @@ set @old_spider_quick_page_byte= @@spider_quick_page_byte; drop and create databases connection master_1; -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; connection child2_1; SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; -DROP DATABASE IF EXISTS auto_test_remote; CREATE DATABASE auto_test_remote; USE auto_test_remote; connection child2_2; SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; -DROP DATABASE IF EXISTS auto_test_remote2; CREATE DATABASE auto_test_remote2; USE auto_test_remote2; create table and insert connection child2_1; -CHILD2_1_DROP_TABLES CHILD2_1_CREATE_TABLES TRUNCATE TABLE mysql.general_log; connection child2_2; -CHILD2_2_DROP_TABLES CHILD2_2_CREATE_TABLES TRUNCATE TABLE mysql.general_log; connection master_1; -DROP TABLE IF EXISTS tbl_a; -DROP TABLE IF EXISTS tbl_b; CREATE TABLE tbl_a ( pkey int NOT NULL, PRIMARY KEY (pkey) diff --git a/storage/spider/mysql-test/spider/t/quick_mode_0.test b/storage/spider/mysql-test/spider/t/quick_mode_0.test index ffb665c0604..6945d97a049 100644 --- a/storage/spider/mysql-test/spider/t/quick_mode_0.test +++ b/storage/spider/mysql-test/spider/t/quick_mode_0.test @@ -3,7 +3,6 @@ --echo drop and create databases --connection master_1 --disable_warnings -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; if ($USE_CHILD_GROUP2) @@ -14,7 +13,6 @@ if ($USE_CHILD_GROUP2) SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; } - DROP DATABASE IF EXISTS auto_test_remote; CREATE DATABASE auto_test_remote; USE auto_test_remote; --connection child2_2 @@ -23,7 +21,6 @@ if ($USE_CHILD_GROUP2) SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; } - DROP DATABASE IF EXISTS auto_test_remote2; CREATE DATABASE auto_test_remote2; USE auto_test_remote2; } @@ -42,12 +39,8 @@ if ($USE_CHILD_GROUP2) if ($OUTPUT_CHILD_GROUP2) { --disable_query_log - echo CHILD2_1_DROP_TABLES; echo CHILD2_1_CREATE_TABLES; } - --disable_warnings - eval $CHILD2_1_DROP_TABLES; - --enable_warnings eval $CHILD2_1_CREATE_TABLES; if ($OUTPUT_CHILD_GROUP2) { @@ -61,12 +54,8 @@ if ($USE_CHILD_GROUP2) if ($OUTPUT_CHILD_GROUP2) { --disable_query_log - echo CHILD2_2_DROP_TABLES; echo CHILD2_2_CREATE_TABLES; } - --disable_warnings - eval $CHILD2_2_DROP_TABLES; - --enable_warnings eval $CHILD2_2_CREATE_TABLES; if ($OUTPUT_CHILD_GROUP2) { @@ -83,10 +72,6 @@ if ($USE_CHILD_GROUP2) } } --connection master_1 ---disable_warnings -DROP TABLE IF EXISTS tbl_a; -DROP TABLE IF EXISTS tbl_b; ---enable_warnings --disable_query_log echo CREATE TABLE tbl_a ( pkey int NOT NULL, diff --git a/storage/spider/mysql-test/spider/t/quick_mode_1.test b/storage/spider/mysql-test/spider/t/quick_mode_1.test index 70d61d087e3..d382d5dbe95 100644 --- a/storage/spider/mysql-test/spider/t/quick_mode_1.test +++ b/storage/spider/mysql-test/spider/t/quick_mode_1.test @@ -3,7 +3,6 @@ --echo drop and create databases --connection master_1 --disable_warnings -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; if ($USE_CHILD_GROUP2) @@ -14,7 +13,6 @@ if ($USE_CHILD_GROUP2) SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; } - DROP DATABASE IF EXISTS auto_test_remote; CREATE DATABASE auto_test_remote; USE auto_test_remote; --connection child2_2 @@ -23,7 +21,6 @@ if ($USE_CHILD_GROUP2) SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; } - DROP DATABASE IF EXISTS auto_test_remote2; CREATE DATABASE auto_test_remote2; USE auto_test_remote2; } @@ -42,12 +39,8 @@ if ($USE_CHILD_GROUP2) if ($OUTPUT_CHILD_GROUP2) { --disable_query_log - echo CHILD2_1_DROP_TABLES; echo CHILD2_1_CREATE_TABLES; } - --disable_warnings - eval $CHILD2_1_DROP_TABLES; - --enable_warnings eval $CHILD2_1_CREATE_TABLES; if ($OUTPUT_CHILD_GROUP2) { @@ -61,12 +54,8 @@ if ($USE_CHILD_GROUP2) if ($OUTPUT_CHILD_GROUP2) { --disable_query_log - echo CHILD2_2_DROP_TABLES; echo CHILD2_2_CREATE_TABLES; } - --disable_warnings - eval $CHILD2_2_DROP_TABLES; - --enable_warnings eval $CHILD2_2_CREATE_TABLES; if ($OUTPUT_CHILD_GROUP2) { @@ -83,10 +72,6 @@ if ($USE_CHILD_GROUP2) } } --connection master_1 ---disable_warnings -DROP TABLE IF EXISTS tbl_a; -DROP TABLE IF EXISTS tbl_b; ---enable_warnings --disable_query_log echo CREATE TABLE tbl_a ( pkey int NOT NULL, diff --git a/storage/spider/mysql-test/spider/t/quick_mode_2.test b/storage/spider/mysql-test/spider/t/quick_mode_2.test index 71e7b0338dc..ebb889868a6 100644 --- a/storage/spider/mysql-test/spider/t/quick_mode_2.test +++ b/storage/spider/mysql-test/spider/t/quick_mode_2.test @@ -3,7 +3,6 @@ --echo drop and create databases --connection master_1 --disable_warnings -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; if ($USE_CHILD_GROUP2) @@ -14,7 +13,6 @@ if ($USE_CHILD_GROUP2) SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; } - DROP DATABASE IF EXISTS auto_test_remote; CREATE DATABASE auto_test_remote; USE auto_test_remote; --connection child2_2 @@ -23,7 +21,6 @@ if ($USE_CHILD_GROUP2) SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; } - DROP DATABASE IF EXISTS auto_test_remote2; CREATE DATABASE auto_test_remote2; USE auto_test_remote2; } @@ -42,12 +39,8 @@ if ($USE_CHILD_GROUP2) if ($OUTPUT_CHILD_GROUP2) { --disable_query_log - echo CHILD2_1_DROP_TABLES; echo CHILD2_1_CREATE_TABLES; } - --disable_warnings - eval $CHILD2_1_DROP_TABLES; - --enable_warnings eval $CHILD2_1_CREATE_TABLES; if ($OUTPUT_CHILD_GROUP2) { @@ -61,12 +54,8 @@ if ($USE_CHILD_GROUP2) if ($OUTPUT_CHILD_GROUP2) { --disable_query_log - echo CHILD2_2_DROP_TABLES; echo CHILD2_2_CREATE_TABLES; } - --disable_warnings - eval $CHILD2_2_DROP_TABLES; - --enable_warnings eval $CHILD2_2_CREATE_TABLES; if ($OUTPUT_CHILD_GROUP2) { @@ -83,10 +72,6 @@ if ($USE_CHILD_GROUP2) } } --connection master_1 ---disable_warnings -DROP TABLE IF EXISTS tbl_a; -DROP TABLE IF EXISTS tbl_b; ---enable_warnings --disable_query_log echo CREATE TABLE tbl_a ( pkey int NOT NULL, diff --git a/storage/spider/mysql-test/spider/t/quick_mode_3.test b/storage/spider/mysql-test/spider/t/quick_mode_3.test index 000edd4fdff..5992284f301 100644 --- a/storage/spider/mysql-test/spider/t/quick_mode_3.test +++ b/storage/spider/mysql-test/spider/t/quick_mode_3.test @@ -3,7 +3,6 @@ --echo drop and create databases --connection master_1 --disable_warnings -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; if ($USE_CHILD_GROUP2) @@ -14,7 +13,6 @@ if ($USE_CHILD_GROUP2) SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; } - DROP DATABASE IF EXISTS auto_test_remote; CREATE DATABASE auto_test_remote; USE auto_test_remote; --connection child2_2 @@ -23,7 +21,6 @@ if ($USE_CHILD_GROUP2) SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; } - DROP DATABASE IF EXISTS auto_test_remote2; CREATE DATABASE auto_test_remote2; USE auto_test_remote2; } @@ -42,12 +39,8 @@ if ($USE_CHILD_GROUP2) if ($OUTPUT_CHILD_GROUP2) { --disable_query_log - echo CHILD2_1_DROP_TABLES; echo CHILD2_1_CREATE_TABLES; } - --disable_warnings - eval $CHILD2_1_DROP_TABLES; - --enable_warnings eval $CHILD2_1_CREATE_TABLES; if ($OUTPUT_CHILD_GROUP2) { @@ -61,12 +54,8 @@ if ($USE_CHILD_GROUP2) if ($OUTPUT_CHILD_GROUP2) { --disable_query_log - echo CHILD2_2_DROP_TABLES; echo CHILD2_2_CREATE_TABLES; } - --disable_warnings - eval $CHILD2_2_DROP_TABLES; - --enable_warnings eval $CHILD2_2_CREATE_TABLES; if ($OUTPUT_CHILD_GROUP2) { @@ -83,10 +72,6 @@ if ($USE_CHILD_GROUP2) } } --connection master_1 ---disable_warnings -DROP TABLE IF EXISTS tbl_a; -DROP TABLE IF EXISTS tbl_b; ---enable_warnings --disable_query_log echo CREATE TABLE tbl_a ( pkey int NOT NULL, From ea347fcb28167efc99db5c3f24c1baa2b57d6e86 Mon Sep 17 00:00:00 2001 From: Kentoku Date: Tue, 25 Dec 2018 00:22:45 +0900 Subject: [PATCH 14/91] remove unnecessary drop database/table from slave_trx_isolation.test add simplified slave_trx_isolation.test --- .../include/slave_trx_isolation_deinit.inc | 15 +++ .../include/slave_trx_isolation_init.inc | 35 +++++++ .../bugfix/r/slave_trx_isolation.result | 99 +++++++++++++++++++ .../spider/bugfix/t/slave_trx_isolation.cnf | 4 + .../spider/bugfix/t/slave_trx_isolation.test | 95 ++++++++++++++++++ .../spider/r/slave_trx_isolation.result | 9 +- .../spider/t/slave_trx_isolation.test | 18 ---- 7 files changed, 250 insertions(+), 25 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/include/slave_trx_isolation_deinit.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/slave_trx_isolation_init.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test diff --git a/storage/spider/mysql-test/spider/bugfix/include/slave_trx_isolation_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/slave_trx_isolation_deinit.inc new file mode 100644 index 00000000000..7c20b2bc99e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/slave_trx_isolation_deinit.inc @@ -0,0 +1,15 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--connection slave1_1 +set global spider_slave_trx_isolation= @old_spider_slave_trx_isolation; +--disable_warnings +--disable_query_log +--disable_result_log +--source ../include/deinit_spider.inc +--source ../t/slave_test_deinit.inc +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/slave_trx_isolation_init.inc b/storage/spider/mysql-test/spider/bugfix/include/slave_trx_isolation_init.inc new file mode 100644 index 00000000000..3a058a55303 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/slave_trx_isolation_init.inc @@ -0,0 +1,35 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--source ../t/slave_test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'; +--connection slave1_1 +--disable_warnings +--disable_query_log +--disable_result_log +--source ../include/init_spider.inc +--enable_result_log +--enable_query_log +--enable_warnings +set @old_spider_slave_trx_isolation= @@spider_slave_trx_isolation; +set global spider_slave_trx_isolation= 1; diff --git a/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result b/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result new file mode 100644 index 00000000000..06581a604a2 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result @@ -0,0 +1,99 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 +for slave1_1 +connection slave1_1; +set @old_spider_slave_trx_isolation= @@spider_slave_trx_isolation; +set global spider_slave_trx_isolation= 1; + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection slave1_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +connection slave1_1; +connection master_1; +SET SESSION sql_log_bin= 0; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE2 MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +SET SESSION sql_log_bin= 1; +connection slave1_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +connection master_1; +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +connection slave1_1; +connection master_1; +SET SESSION sql_log_bin= 0; +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'; +argument +set session time_zone = '+00:00' +SET NAMES utf8 +set session transaction isolation level read committed;set session autocommit = 1;start transaction +SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +connection slave1_1; +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection slave1_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +connection slave1_1; +set global spider_slave_trx_isolation= @old_spider_slave_trx_isolation; +for slave1_1 +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.cnf b/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.cnf new file mode 100644 index 00000000000..45019d6c537 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.cnf @@ -0,0 +1,4 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf +!include ../my_4_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test b/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test new file mode 100644 index 00000000000..652fbb1c11c --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/slave_trx_isolation.test @@ -0,0 +1,95 @@ +--source ../include/slave_trx_isolation_init.inc +--echo +--echo drop and create databases +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection slave1_1 +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +save_master_pos; + +--connection slave1_1 +sync_with_master; + +--connection master_1 +SET SESSION sql_log_bin= 0; +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE2 MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE2 $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log +SET SESSION sql_log_bin= 1; + +--connection slave1_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log + +--connection master_1 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +save_master_pos; + +--connection slave1_1 +sync_with_master; + +--connection master_1 +SET SESSION sql_log_bin= 0; + +--connection child2_1 +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--connection slave1_1 +SELECT pkey FROM tbl_a ORDER BY pkey; + +--echo +--echo deinit +--disable_warnings +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection slave1_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/slave_trx_isolation_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/mysql-test/spider/r/slave_trx_isolation.result b/storage/spider/mysql-test/spider/r/slave_trx_isolation.result index 167739beaad..7d9ba40cab3 100644 --- a/storage/spider/mysql-test/spider/r/slave_trx_isolation.result +++ b/storage/spider/mysql-test/spider/r/slave_trx_isolation.result @@ -14,37 +14,31 @@ set global spider_slave_trx_isolation= 1; drop and create databases connection master_1; -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; connection slave1_1; -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; connection child2_1; SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; -DROP DATABASE IF EXISTS auto_test_remote; CREATE DATABASE auto_test_remote; USE auto_test_remote; create table and insert connection child2_1; -CHILD2_1_DROP_TABLES CHILD2_1_CREATE_TABLES TRUNCATE TABLE mysql.general_log; connection master_1; connection slave1_1; connection master_1; -DROP TABLE IF EXISTS tbl_a; +SET SESSION sql_log_bin= 0; CREATE TABLE tbl_a ( pkey int NOT NULL, PRIMARY KEY (pkey) ) MASTER_1_ENGINE2 MASTER_1_CHARSET MASTER_1_COMMENT_2_1 -connection master_1; SET SESSION sql_log_bin= 1; connection slave1_1; -DROP TABLE IF EXISTS tbl_a; CREATE TABLE tbl_a ( pkey int NOT NULL, PRIMARY KEY (pkey) @@ -53,6 +47,7 @@ connection master_1; INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); connection slave1_1; connection master_1; +SET SESSION sql_log_bin= 0; connection child2_1; SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'; argument diff --git a/storage/spider/mysql-test/spider/t/slave_trx_isolation.test b/storage/spider/mysql-test/spider/t/slave_trx_isolation.test index d1dea8546b9..507e5340779 100644 --- a/storage/spider/mysql-test/spider/t/slave_trx_isolation.test +++ b/storage/spider/mysql-test/spider/t/slave_trx_isolation.test @@ -3,13 +3,11 @@ --echo drop and create databases --connection master_1 --disable_warnings -DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; if ($USE_REPLICATION) { --connection slave1_1 - DROP DATABASE IF EXISTS auto_test_local; CREATE DATABASE auto_test_local; USE auto_test_local; } @@ -21,7 +19,6 @@ if ($USE_CHILD_GROUP2) SET @old_log_output = @@global.log_output; SET GLOBAL log_output = 'TABLE,FILE'; } - DROP DATABASE IF EXISTS auto_test_remote; CREATE DATABASE auto_test_remote; USE auto_test_remote; } @@ -40,12 +37,8 @@ if ($USE_CHILD_GROUP2) if ($OUTPUT_CHILD_GROUP2) { --disable_query_log - echo CHILD2_1_DROP_TABLES; echo CHILD2_1_CREATE_TABLES; } - --disable_warnings - eval $CHILD2_1_DROP_TABLES; - --enable_warnings eval $CHILD2_1_CREATE_TABLES; if ($OUTPUT_CHILD_GROUP2) { @@ -68,13 +61,8 @@ if ($USE_REPLICATION) --connection slave1_1 sync_with_master; --connection master_1 - --disable_query_log SET SESSION sql_log_bin= 0; - --enable_query_log } ---disable_warnings -DROP TABLE IF EXISTS tbl_a; ---enable_warnings --disable_query_log echo CREATE TABLE tbl_a ( pkey int NOT NULL, @@ -85,14 +73,10 @@ eval CREATE TABLE tbl_a ( PRIMARY KEY (pkey) ) $MASTER_1_ENGINE2 $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; --enable_query_log ---connection master_1 if ($USE_REPLICATION) { SET SESSION sql_log_bin= 1; --connection slave1_1 - --disable_warnings - DROP TABLE IF EXISTS tbl_a; - --enable_warnings --disable_query_log echo CREATE TABLE tbl_a ( pkey int NOT NULL, @@ -112,9 +96,7 @@ if ($USE_REPLICATION) --connection slave1_1 sync_with_master; --connection master_1 - --disable_query_log SET SESSION sql_log_bin= 0; - --enable_query_log } if ($USE_CHILD_GROUP2) { From 470c1b8d564bdc3574376d2c50a0dac783c5b3da Mon Sep 17 00:00:00 2001 From: Kentoku Date: Mon, 31 Dec 2018 23:42:49 +0900 Subject: [PATCH 15/91] Fix an error at using spider_direct_sql with temporary table --- .../direct_sql_with_tmp_table_deinit.inc | 7 ++++ .../direct_sql_with_tmp_table_init.inc | 9 +++++ .../bugfix/r/direct_sql_with_tmp_table.result | 33 +++++++++++++++++ .../bugfix/t/direct_sql_with_tmp_table.cnf | 3 ++ .../bugfix/t/direct_sql_with_tmp_table.test | 35 +++++++++++++++++++ storage/spider/spd_direct_sql.cc | 2 +- storage/spider/spd_include.h | 4 +-- storage/spider/spd_sys_table.cc | 17 +++++++++ storage/spider/spd_sys_table.h | 5 +++ 9 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/include/direct_sql_with_tmp_table_deinit.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/direct_sql_with_tmp_table_init.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/r/direct_sql_with_tmp_table.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/direct_sql_with_tmp_table.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/direct_sql_with_tmp_table.test diff --git a/storage/spider/mysql-test/spider/bugfix/include/direct_sql_with_tmp_table_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/direct_sql_with_tmp_table_deinit.inc new file mode 100644 index 00000000000..ecb5622af14 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/direct_sql_with_tmp_table_deinit.inc @@ -0,0 +1,7 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/direct_sql_with_tmp_table_init.inc b/storage/spider/mysql-test/spider/bugfix/include/direct_sql_with_tmp_table_init.inc new file mode 100644 index 00000000000..7b58bd3e726 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/direct_sql_with_tmp_table_init.inc @@ -0,0 +1,9 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +let $DIRECT_SQL_COMMAND= + SELECT spider_direct_sql('SELECT 22', 'tmp_a', 'srv "s_2_1", database "test"'); diff --git a/storage/spider/mysql-test/spider/bugfix/r/direct_sql_with_tmp_table.result b/storage/spider/mysql-test/spider/bugfix/r/direct_sql_with_tmp_table.result new file mode 100644 index 00000000000..65beb8a43dd --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/direct_sql_with_tmp_table.result @@ -0,0 +1,33 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +CREATE TEMPORARY TABLE tmp_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE2 +SELECT spider_direct_sql('SELECT 22', 'tmp_a', 'srv "s_2_1", database "test"'); +spider_direct_sql('SELECT 22', 'tmp_a', 'srv "s_2_1", database "test"') +1 +SELECT pkey FROM tmp_a; +pkey +22 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/direct_sql_with_tmp_table.cnf b/storage/spider/mysql-test/spider/bugfix/t/direct_sql_with_tmp_table.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/direct_sql_with_tmp_table.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/direct_sql_with_tmp_table.test b/storage/spider/mysql-test/spider/bugfix/t/direct_sql_with_tmp_table.test new file mode 100644 index 00000000000..139af5c83c9 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/direct_sql_with_tmp_table.test @@ -0,0 +1,35 @@ +--source ../include/direct_sql_with_tmp_table_init.inc +--echo +--echo drop and create databases + +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; +--enable_warnings + +--disable_query_log +echo CREATE TEMPORARY TABLE tmp_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE2; +eval CREATE TEMPORARY TABLE tmp_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE2; +--enable_query_log + +eval $DIRECT_SQL_COMMAND; +SELECT pkey FROM tmp_a; + +--echo +--echo deinit +--disable_warnings + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--enable_warnings +--source ../include/direct_sql_with_tmp_table_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index 65d5142e1f1..aee66d0336b 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -1721,7 +1721,7 @@ long long spider_direct_sql_body( direct_sql->table_names[roop_count]; #endif if (!(direct_sql->tables[roop_count] = - SPIDER_find_temporary_table(thd, &table_list))) + spider_find_temporary_table(thd, &table_list))) { #if MYSQL_VERSION_ID < 50500 #else diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index 23bbff22fbb..37ec2d8c608 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -160,9 +160,7 @@ #if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100201 #define SPIDER_HAS_MY_CHARLEN -#define SPIDER_find_temporary_table(A,B) A->find_temporary_table(B) -#else -#define SPIDER_find_temporary_table(A,B) find_temporary_table(A,B) +#define SPIDER_open_temporary_table #endif #if defined(MARIADB_BASE_VERSION) diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc index cd1c56a077e..8f8605b85bd 100644 --- a/storage/spider/spd_sys_table.cc +++ b/storage/spider/spd_sys_table.cc @@ -3489,3 +3489,20 @@ void spider_rm_sys_tmp_table_for_result( tmp_tbl_prm->field_count = 3; DBUG_VOID_RETURN; } + +TABLE *spider_find_temporary_table( + THD *thd, + TABLE_LIST *table_list +) { + DBUG_ENTER("spider_find_temporary_table"); +#ifdef SPIDER_open_temporary_table + if (thd->open_temporary_table(table_list)) + { + DBUG_RETURN(NULL); + } else { + DBUG_RETURN(table_list->table); + } +#else + DBUG_RETURN(find_temporary_table(A,B)); +#endif +} diff --git a/storage/spider/spd_sys_table.h b/storage/spider/spd_sys_table.h index 857109edb38..0fdb8cde6a2 100644 --- a/storage/spider/spd_sys_table.h +++ b/storage/spider/spd_sys_table.h @@ -678,3 +678,8 @@ void spider_rm_sys_tmp_table_for_result( TABLE *tmp_table, TMP_TABLE_PARAM *tmp_tbl_prm ); + +TABLE *spider_find_temporary_table( + THD *thd, + TABLE_LIST *table_list +); From 4e599c74bb673e6d752bdacffbe014cbfd033b0a Mon Sep 17 00:00:00 2001 From: Kentoku Date: Wed, 30 Jan 2019 03:29:37 +0900 Subject: [PATCH 16/91] MDEV-18313 Supports 'wrapper mariadb' for connection information --- storage/spider/CMakeLists.txt | 2 +- .../bugfix/include/wrapper_mariadb_deinit.inc | 11 + .../bugfix/include/wrapper_mariadb_init.inc | 24 + .../spider/bugfix/r/wrapper_mariadb.result | 78 + .../spider/bugfix/t/wrapper_mariadb.cnf | 3 + .../spider/bugfix/t/wrapper_mariadb.test | 69 + storage/spider/spd_db_handlersocket.cc | 7 +- storage/spider/spd_db_include.cc | 51 + storage/spider/spd_db_include.h | 23 +- storage/spider/spd_db_mysql.cc | 2071 ++++++++++------- storage/spider/spd_db_mysql.h | 196 +- storage/spider/spd_db_oracle.cc | 9 +- storage/spider/spd_table.cc | 8 + 13 files changed, 1618 insertions(+), 934 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/include/wrapper_mariadb_deinit.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/include/wrapper_mariadb_init.inc create mode 100644 storage/spider/mysql-test/spider/bugfix/r/wrapper_mariadb.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/wrapper_mariadb.cnf create mode 100644 storage/spider/mysql-test/spider/bugfix/t/wrapper_mariadb.test create mode 100644 storage/spider/spd_db_include.cc diff --git a/storage/spider/CMakeLists.txt b/storage/spider/CMakeLists.txt index 21278dde3b3..62dfc968579 100644 --- a/storage/spider/CMakeLists.txt +++ b/storage/spider/CMakeLists.txt @@ -18,7 +18,7 @@ SET(SPIDER_SOURCES spd_table.cc spd_direct_sql.cc spd_udf.cc spd_ping_table.cc spd_copy_tables.cc spd_i_s.cc spd_malloc.cc ha_spider.cc spd_udf.def spd_db_mysql.cc spd_db_handlersocket.cc spd_db_oracle.cc - spd_group_by_handler.cc + spd_group_by_handler.cc spd_db_include.cc hs_client/config.cpp hs_client/escape.cpp hs_client/fatal.cpp hs_client/hstcpcli.cpp hs_client/socket.cpp hs_client/string_util.cpp ) diff --git a/storage/spider/mysql-test/spider/bugfix/include/wrapper_mariadb_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/wrapper_mariadb_deinit.inc new file mode 100644 index 00000000000..76b7582abfe --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/wrapper_mariadb_deinit.inc @@ -0,0 +1,11 @@ +--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP +--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP +--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP +--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_deinit.inc +--enable_result_log +--enable_query_log +--enable_warnings diff --git a/storage/spider/mysql-test/spider/bugfix/include/wrapper_mariadb_init.inc b/storage/spider/mysql-test/spider/bugfix/include/wrapper_mariadb_init.inc new file mode 100644 index 00000000000..df3d44c39bc --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/include/wrapper_mariadb_init.inc @@ -0,0 +1,24 @@ +--disable_warnings +--disable_query_log +--disable_result_log +--source ../t/test_init.inc +--enable_result_log +--enable_query_log +--enable_warnings +--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1 +let $MASTER_1_COMMENT_2_1= + COMMENT='table "tbl_a", srv "s_2_1", wrapper "mariadb"'; +--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES +let $CHILD2_1_DROP_TABLES= + DROP TABLE IF EXISTS tbl_a; +--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES +let $CHILD2_1_CREATE_TABLES= + CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) + ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET; +--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES +let $CHILD2_1_SELECT_TABLES= + SELECT pkey FROM tbl_a ORDER BY pkey; +let $CHILD2_1_SELECT_ARGUMENT1= + SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; diff --git a/storage/spider/mysql-test/spider/bugfix/r/wrapper_mariadb.result b/storage/spider/mysql-test/spider/bugfix/r/wrapper_mariadb.result new file mode 100644 index 00000000000..7c01421fa13 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/wrapper_mariadb.result @@ -0,0 +1,78 @@ +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +this test is for MDEV-18313 + +drop and create databases +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +connection child2_1; +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; + +create table and insert +connection child2_1; +CHILD2_1_CREATE_TABLES +TRUNCATE TABLE mysql.general_log; +connection master_1; +CREATE TABLE tbl_a ( +pkey int NOT NULL, +PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1 +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +select test +connection child2_1; +TRUNCATE TABLE mysql.general_log; +connection master_1; +SELECT * FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +connection child2_1; +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'; +argument +select t0.`pkey` `pkey` from `auto_test_remote`.`tbl_a` t0 order by `pkey` +SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %' +SELECT pkey FROM tbl_a ORDER BY pkey; +pkey +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 + +deinit +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; +for master_1 +for child2 +child2_1 +child2_2 +child2_3 +for child3 + +end of test diff --git a/storage/spider/mysql-test/spider/bugfix/t/wrapper_mariadb.cnf b/storage/spider/mysql-test/spider/bugfix/t/wrapper_mariadb.cnf new file mode 100644 index 00000000000..05dfd8a0bce --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/wrapper_mariadb.cnf @@ -0,0 +1,3 @@ +!include include/default_mysqld.cnf +!include ../my_1_1.cnf +!include ../my_2_1.cnf diff --git a/storage/spider/mysql-test/spider/bugfix/t/wrapper_mariadb.test b/storage/spider/mysql-test/spider/bugfix/t/wrapper_mariadb.test new file mode 100644 index 00000000000..0102155b5ab --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/wrapper_mariadb.test @@ -0,0 +1,69 @@ +--source ../include/wrapper_mariadb_init.inc +--echo +--echo this test is for MDEV-18313 +--echo +--echo drop and create databases + +--connection master_1 +--disable_warnings +CREATE DATABASE auto_test_local; +USE auto_test_local; + +--connection child2_1 +SET @old_log_output = @@global.log_output; +SET GLOBAL log_output = 'TABLE,FILE'; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +--enable_warnings + +--echo +--echo create table and insert + +--connection child2_1 +--disable_query_log +echo CHILD2_1_CREATE_TABLES; +eval $CHILD2_1_CREATE_TABLES; +--enable_query_log +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +--disable_query_log +echo CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1; +eval CREATE TABLE tbl_a ( + pkey int NOT NULL, + PRIMARY KEY (pkey) +) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1; +--enable_query_log +INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +--echo +--echo select test + +--connection child2_1 +TRUNCATE TABLE mysql.general_log; + +--connection master_1 +SELECT * FROM tbl_a ORDER BY pkey; + +--connection child2_1 +eval $CHILD2_1_SELECT_ARGUMENT1; +eval $CHILD2_1_SELECT_TABLES; + +--echo +--echo deinit +--disable_warnings + +--connection master_1 +DROP DATABASE IF EXISTS auto_test_local; + +--connection child2_1 +DROP DATABASE IF EXISTS auto_test_remote; +SET GLOBAL log_output = @old_log_output; + +--enable_warnings +--source ../include/wrapper_mariadb_deinit.inc +--echo +--echo end of test diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc index 4aebc7811b4..37bbe530723 100644 --- a/storage/spider/spd_db_handlersocket.cc +++ b/storage/spider/spd_db_handlersocket.cc @@ -500,7 +500,7 @@ SPIDER_DB_ROW *spider_db_handlersocket_row::clone() uint i; DBUG_ENTER("spider_db_handlersocket_row::clone"); DBUG_PRINT("info",("spider this=%p", this)); - if (!(clone_row = new spider_db_handlersocket_row())) + if (!(clone_row = new spider_db_handlersocket_row(dbton_id))) { DBUG_RETURN(NULL); } @@ -603,7 +603,7 @@ bool spider_db_handlersocket_result_buffer::check_size( spider_db_handlersocket_result::spider_db_handlersocket_result( SPIDER_DB_CONN *in_db_conn -) : spider_db_result(in_db_conn, spider_dbton_handlersocket.dbton_id) +) : spider_db_result(in_db_conn), row(in_db_conn->dbton_id) { DBUG_ENTER("spider_db_handlersocket_result::spider_db_handlersocket_result"); DBUG_PRINT("info",("spider this=%p", this)); @@ -3953,7 +3953,8 @@ int spider_db_handlersocket_util::append_having( spider_handlersocket_share::spider_handlersocket_share( st_spider_share *share ) : spider_db_share( - share + share, + spider_dbton_handlersocket.dbton_id ), table_names_str(NULL), db_names_str(NULL), diff --git a/storage/spider/spd_db_include.cc b/storage/spider/spd_db_include.cc new file mode 100644 index 00000000000..2910aa97690 --- /dev/null +++ b/storage/spider/spd_db_include.cc @@ -0,0 +1,51 @@ +/* Copyright (C) 2018-2019 Kentoku Shiba + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#define MYSQL_SERVER 1 +#include +#include "mysql_version.h" +#include "spd_environ.h" +#if MYSQL_VERSION_ID < 50500 +#include "mysql_priv.h" +#include +#else +#include "sql_priv.h" +#include "probes_mysql.h" +#include "sql_class.h" +#endif +#include "sql_common.h" +#include +#include +#include "spd_err.h" +#include "spd_db_include.h" +#include "spd_include.h" + +spider_db_result::spider_db_result( + SPIDER_DB_CONN *in_db_conn +) : db_conn(in_db_conn), dbton_id(in_db_conn->dbton_id) +{ + DBUG_ENTER("spider_db_result::spider_db_result"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_conn::spider_db_conn( + SPIDER_CONN *in_conn +) : conn(in_conn), dbton_id(in_conn->dbton_id) +{ + DBUG_ENTER("spider_db_conn::spider_db_conn"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index cc4d2bcd3a1..64cee006c65 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -21,6 +21,7 @@ #define SPIDER_DBTON_SIZE 15 #define SPIDER_DB_WRAPPER_MYSQL "mysql" +#define SPIDER_DB_WRAPPER_MARIADB "mariadb" #if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100204 #define PLUGIN_VAR_CAN_MEMALLOC @@ -795,6 +796,7 @@ struct st_spider_db_request_key class spider_db_util { public: + uint dbton_id; spider_db_util() {} virtual ~spider_db_util() {} virtual int append_name( @@ -961,8 +963,7 @@ protected: SPIDER_DB_CONN *db_conn; public: uint dbton_id; - spider_db_result(SPIDER_DB_CONN *in_db_conn, uint in_dbton_id) : - db_conn(in_db_conn), dbton_id(in_dbton_id) {} + spider_db_result(SPIDER_DB_CONN *in_db_conn); virtual ~spider_db_result() {} virtual bool has_result() = 0; virtual void free_result() = 0; @@ -1028,9 +1029,10 @@ class spider_db_conn protected: SPIDER_CONN *conn; public: + uint dbton_id; spider_db_conn( - SPIDER_CONN *conn - ) : conn(conn) {} + SPIDER_CONN *in_conn + ); virtual ~spider_db_conn() {} virtual int init() = 0; virtual bool is_connected() = 0; @@ -1229,8 +1231,12 @@ protected: const char *mem_calc_file_name; ulong mem_calc_line_no; public: + uint dbton_id; st_spider_share *spider_share; - spider_db_share(st_spider_share *share) : spider_share(share) {} + spider_db_share( + st_spider_share *share, + uint dbton_id + ) : dbton_id(dbton_id), spider_share(share) {} virtual ~spider_db_share() {} virtual int init() = 0; virtual uint get_column_name_length( @@ -1264,6 +1270,7 @@ protected: const char *mem_calc_file_name; ulong mem_calc_line_no; public: + uint dbton_id; ha_spider *spider; spider_db_share *db_share; int first_link_idx; @@ -1271,7 +1278,8 @@ public: SPIDER_LINK_IDX_CHAIN *link_idx_chain; #endif spider_db_handler(ha_spider *spider, spider_db_share *db_share) : - spider(spider), db_share(db_share), first_link_idx(-1) {} + dbton_id(db_share->dbton_id), spider(spider), db_share(db_share), + first_link_idx(-1) {} virtual ~spider_db_handler() {} virtual int init() = 0; virtual int append_index_hint( @@ -1750,9 +1758,10 @@ public: class spider_db_copy_table { public: + uint dbton_id; spider_db_share *db_share; spider_db_copy_table(spider_db_share *db_share) : - db_share(db_share) {} + dbton_id(db_share->dbton_id), db_share(db_share) {} virtual ~spider_db_copy_table() {} virtual int init() = 0; virtual void set_sql_charset( diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index ceb38f886aa..262e47120ce 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -57,6 +57,9 @@ extern HASH spider_ipport_conns; extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; extern const char spider_dig_upper[]; +spider_db_mysql_util spider_db_mysql_utility; +spider_db_mariadb_util spider_db_mariadb_utility; + #define SPIDER_SQL_NAME_QUOTE_STR "`" #define SPIDER_SQL_NAME_QUOTE_LEN (sizeof(SPIDER_SQL_NAME_QUOTE_STR) - 1) static const char *name_quote_str = SPIDER_SQL_NAME_QUOTE_STR; @@ -197,12 +200,24 @@ int spider_mysql_init() DBUG_RETURN(0); } +int spider_mariadb_init() +{ + DBUG_ENTER("spider_mariadb_init"); + DBUG_RETURN(0); +} + int spider_mysql_deinit() { DBUG_ENTER("spider_mysql_deinit"); DBUG_RETURN(0); } +int spider_mariadb_deinit() +{ + DBUG_ENTER("spider_mariadb_deinit"); + DBUG_RETURN(0); +} + spider_db_share *spider_mysql_create_share( SPIDER_SHARE *share ) { @@ -210,13 +225,29 @@ spider_db_share *spider_mysql_create_share( DBUG_RETURN(new spider_mysql_share(share)); } +spider_db_share *spider_mariadb_create_share( + SPIDER_SHARE *share +) { + DBUG_ENTER("spider_mariadb_create_share"); + DBUG_RETURN(new spider_mariadb_share(share)); +} + spider_db_handler *spider_mysql_create_handler( ha_spider *spider, spider_db_share *db_share ) { DBUG_ENTER("spider_mysql_create_handler"); DBUG_RETURN(new spider_mysql_handler(spider, - (spider_mysql_share *) db_share)); + (spider_mbase_share *) db_share)); +} + +spider_db_handler *spider_mariadb_create_handler( + ha_spider *spider, + spider_db_share *db_share +) { + DBUG_ENTER("spider_mariadb_create_handler"); + DBUG_RETURN(new spider_mariadb_handler(spider, + (spider_mbase_share *) db_share)); } spider_db_copy_table *spider_mysql_create_copy_table( @@ -224,7 +255,15 @@ spider_db_copy_table *spider_mysql_create_copy_table( ) { DBUG_ENTER("spider_mysql_create_copy_table"); DBUG_RETURN(new spider_mysql_copy_table( - (spider_mysql_share *) db_share)); + (spider_mbase_share *) db_share)); +} + +spider_db_copy_table *spider_mariadb_create_copy_table( + spider_db_share *db_share +) { + DBUG_ENTER("spider_mariadb_create_copy_table"); + DBUG_RETURN(new spider_mariadb_copy_table( + (spider_mbase_share *) db_share)); } SPIDER_DB_CONN *spider_mysql_create_conn( @@ -234,13 +273,24 @@ SPIDER_DB_CONN *spider_mysql_create_conn( DBUG_RETURN(new spider_db_mysql(conn)); } +SPIDER_DB_CONN *spider_mariadb_create_conn( + SPIDER_CONN *conn +) { + DBUG_ENTER("spider_mariadb_create_conn"); + DBUG_RETURN(new spider_db_mariadb(conn)); +} + bool spider_mysql_support_direct_join( ) { DBUG_ENTER("spider_mysql_support_direct_join"); DBUG_RETURN(TRUE); } -spider_db_mysql_util spider_db_mysql_utility; +bool spider_mariadb_support_direct_join( +) { + DBUG_ENTER("spider_mariadb_support_direct_join"); + DBUG_RETURN(TRUE); +} SPIDER_DBTON spider_dbton_mysql = { 0, @@ -256,18 +306,49 @@ SPIDER_DBTON spider_dbton_mysql = { &spider_db_mysql_utility }; -spider_db_mysql_row::spider_db_mysql_row() : - spider_db_row(spider_dbton_mysql.dbton_id), +SPIDER_DBTON spider_dbton_mariadb = { + 0, + SPIDER_DB_WRAPPER_MARIADB, + SPIDER_DB_ACCESS_TYPE_SQL, + spider_mariadb_init, + spider_mariadb_deinit, + spider_mariadb_create_share, + spider_mariadb_create_handler, + spider_mariadb_create_copy_table, + spider_mariadb_create_conn, + spider_mariadb_support_direct_join, + &spider_db_mariadb_utility +}; + +spider_db_mbase_row::spider_db_mbase_row( + uint dbton_id +) : spider_db_row(dbton_id), row(NULL), lengths(NULL), cloned(FALSE) +{ + DBUG_ENTER("spider_db_mbase_row::spider_db_mbase_row"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mysql_row::spider_db_mysql_row() : + spider_db_mbase_row(spider_db_mysql_utility.dbton_id) { DBUG_ENTER("spider_db_mysql_row::spider_db_mysql_row"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_VOID_RETURN; } -spider_db_mysql_row::~spider_db_mysql_row() +spider_db_mariadb_row::spider_db_mariadb_row() : + spider_db_mbase_row(spider_db_mariadb_utility.dbton_id) { - DBUG_ENTER("spider_db_mysql_row::~spider_db_mysql_row"); + DBUG_ENTER("spider_db_mariadb_row::spider_db_mariadb_row"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mbase_row::~spider_db_mbase_row() +{ + DBUG_ENTER("spider_db_mbase_row::~spider_db_mbase_row"); DBUG_PRINT("info",("spider this=%p", this)); if (cloned) { @@ -276,11 +357,25 @@ spider_db_mysql_row::~spider_db_mysql_row() DBUG_VOID_RETURN; } -int spider_db_mysql_row::store_to_field( +spider_db_mysql_row::~spider_db_mysql_row() +{ + DBUG_ENTER("spider_db_mysql_row::~spider_db_mysql_row"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mariadb_row::~spider_db_mariadb_row() +{ + DBUG_ENTER("spider_db_mariadb_row::~spider_db_mariadb_row"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +int spider_db_mbase_row::store_to_field( Field *field, CHARSET_INFO *access_charset ) { - DBUG_ENTER("spider_db_mysql_row::store_to_field"); + DBUG_ENTER("spider_db_mbase_row::store_to_field"); DBUG_PRINT("info",("spider this=%p", this)); if (!*row) { @@ -317,10 +412,10 @@ int spider_db_mysql_row::store_to_field( DBUG_RETURN(0); } -int spider_db_mysql_row::append_to_str( +int spider_db_mbase_row::append_to_str( spider_string *str ) { - DBUG_ENTER("spider_db_mysql_row::append_to_str"); + DBUG_ENTER("spider_db_mbase_row::append_to_str"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(*lengths)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -328,11 +423,11 @@ int spider_db_mysql_row::append_to_str( DBUG_RETURN(0); } -int spider_db_mysql_row::append_escaped_to_str( +int spider_db_mbase_row::append_escaped_to_str( spider_string *str, uint dbton_id ) { - DBUG_ENTER("spider_db_mysql_row::append_escaped_to_str"); + DBUG_ENTER("spider_db_mbase_row::append_escaped_to_str"); DBUG_PRINT("info",("spider this=%p", this)); spider_string tmp_str(*row, *lengths + 1, str->charset()); tmp_str.init_calc_mem(133); @@ -343,50 +438,50 @@ int spider_db_mysql_row::append_escaped_to_str( DBUG_RETURN(0); } -void spider_db_mysql_row::first() +void spider_db_mbase_row::first() { - DBUG_ENTER("spider_db_mysql_row::first"); + DBUG_ENTER("spider_db_mbase_row::first"); DBUG_PRINT("info",("spider this=%p", this)); row = row_first; lengths = lengths_first; DBUG_VOID_RETURN; } -void spider_db_mysql_row::next() +void spider_db_mbase_row::next() { - DBUG_ENTER("spider_db_mysql_row::next"); + DBUG_ENTER("spider_db_mbase_row::next"); DBUG_PRINT("info",("spider this=%p", this)); row++; lengths++; DBUG_VOID_RETURN; } -bool spider_db_mysql_row::is_null() +bool spider_db_mbase_row::is_null() { - DBUG_ENTER("spider_db_mysql_row::is_null"); + DBUG_ENTER("spider_db_mbase_row::is_null"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(!(*row)); } -int spider_db_mysql_row::val_int() +int spider_db_mbase_row::val_int() { - DBUG_ENTER("spider_db_mysql_row::val_int"); + DBUG_ENTER("spider_db_mbase_row::val_int"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(*row ? atoi(*row) : 0); } -double spider_db_mysql_row::val_real() +double spider_db_mbase_row::val_real() { - DBUG_ENTER("spider_db_mysql_row::val_real"); + DBUG_ENTER("spider_db_mbase_row::val_real"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(*row ? my_atof(*row) : 0.0); } -my_decimal *spider_db_mysql_row::val_decimal( +my_decimal *spider_db_mbase_row::val_decimal( my_decimal *decimal_value, CHARSET_INFO *access_charset ) { - DBUG_ENTER("spider_db_mysql_row::val_decimal"); + DBUG_ENTER("spider_db_mbase_row::val_decimal"); DBUG_PRINT("info",("spider this=%p", this)); if (!*row) DBUG_RETURN(NULL); @@ -402,16 +497,16 @@ my_decimal *spider_db_mysql_row::val_decimal( DBUG_RETURN(decimal_value); } -SPIDER_DB_ROW *spider_db_mysql_row::clone() +SPIDER_DB_ROW *spider_db_mbase_row::clone() { - spider_db_mysql_row *clone_row; + spider_db_mbase_row *clone_row; char *tmp_char; MYSQL_ROW tmp_row = row_first, ctmp_row; ulong *tmp_lengths = lengths_first; uint row_size, i; - DBUG_ENTER("spider_db_mysql_row::clone"); + DBUG_ENTER("spider_db_mbase_row::clone"); DBUG_PRINT("info",("spider this=%p", this)); - if (!(clone_row = new spider_db_mysql_row())) + if (!(clone_row = new spider_db_mbase_row(dbton_id))) { DBUG_RETURN(NULL); } @@ -464,14 +559,14 @@ SPIDER_DB_ROW *spider_db_mysql_row::clone() DBUG_RETURN((SPIDER_DB_ROW *) clone_row); } -int spider_db_mysql_row::store_to_tmp_table( +int spider_db_mbase_row::store_to_tmp_table( TABLE *tmp_table, spider_string *str ) { uint i; MYSQL_ROW tmp_row = row; ulong *tmp_lengths = lengths; - DBUG_ENTER("spider_db_mysql_row::store_to_tmp_table"); + DBUG_ENTER("spider_db_mbase_row::store_to_tmp_table"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); for (i = 0; i < field_count; i++) @@ -500,11 +595,11 @@ int spider_db_mysql_row::store_to_tmp_table( DBUG_RETURN(tmp_table->file->ha_write_row(tmp_table->record[0])); } -uint spider_db_mysql_row::get_byte_size() +uint spider_db_mbase_row::get_byte_size() { ulong *tmp_lengths = lengths_first; uint i; - DBUG_ENTER("spider_db_mysql_row::get_byte_size"); + DBUG_ENTER("spider_db_mbase_row::get_byte_size"); DBUG_PRINT("info",("spider this=%p", this)); if (!record_size) { @@ -517,18 +612,37 @@ uint spider_db_mysql_row::get_byte_size() DBUG_RETURN(record_size); } -spider_db_mysql_result::spider_db_mysql_result(SPIDER_DB_CONN *in_db_conn) : - spider_db_result(in_db_conn, spider_dbton_mysql.dbton_id), - db_result(NULL) +spider_db_mbase_result::spider_db_mbase_result( + SPIDER_DB_CONN *in_db_conn +) : spider_db_result(in_db_conn), + db_result(NULL), row(in_db_conn->dbton_id) +{ + DBUG_ENTER("spider_db_mbase_result::spider_db_mbase_result"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mysql_result::spider_db_mysql_result( + SPIDER_DB_CONN *in_db_conn +) : spider_db_mbase_result(in_db_conn) { DBUG_ENTER("spider_db_mysql_result::spider_db_mysql_result"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_VOID_RETURN; } -spider_db_mysql_result::~spider_db_mysql_result() +spider_db_mariadb_result::spider_db_mariadb_result( + SPIDER_DB_CONN *in_db_conn +) : spider_db_mbase_result(in_db_conn) { - DBUG_ENTER("spider_db_mysql_result::~spider_db_mysql_result"); + DBUG_ENTER("spider_db_mariadb_result::spider_db_mariadb_result"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mbase_result::~spider_db_mbase_result() +{ + DBUG_ENTER("spider_db_mbase_result::~spider_db_mbase_result"); DBUG_PRINT("info",("spider this=%p", this)); if (db_result) { @@ -537,16 +651,30 @@ spider_db_mysql_result::~spider_db_mysql_result() DBUG_VOID_RETURN; } -bool spider_db_mysql_result::has_result() +spider_db_mysql_result::~spider_db_mysql_result() { - DBUG_ENTER("spider_db_mysql_result::has_result"); + DBUG_ENTER("spider_db_mysql_result::~spider_db_mysql_result"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mariadb_result::~spider_db_mariadb_result() +{ + DBUG_ENTER("spider_db_mariadb_result::~spider_db_mariadb_result"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +bool spider_db_mbase_result::has_result() +{ + DBUG_ENTER("spider_db_mbase_result::has_result"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(db_result); } -void spider_db_mysql_result::free_result() +void spider_db_mbase_result::free_result() { - DBUG_ENTER("spider_db_mysql_result::free_result"); + DBUG_ENTER("spider_db_mbase_result::free_result"); DBUG_PRINT("info",("spider this=%p", this)); /* need 2 times execution design */ if (db_result) @@ -557,24 +685,24 @@ void spider_db_mysql_result::free_result() DBUG_VOID_RETURN; } -SPIDER_DB_ROW *spider_db_mysql_result::current_row() +SPIDER_DB_ROW *spider_db_mbase_result::current_row() { - DBUG_ENTER("spider_db_mysql_result::current_row"); + DBUG_ENTER("spider_db_mbase_result::current_row"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN((SPIDER_DB_ROW *) row.clone()); } -SPIDER_DB_ROW *spider_db_mysql_result::fetch_row() +SPIDER_DB_ROW *spider_db_mbase_result::fetch_row() { - DBUG_ENTER("spider_db_mysql_result::fetch_row"); + DBUG_ENTER("spider_db_mbase_result::fetch_row"); DBUG_PRINT("info",("spider this=%p", this)); if (!(row.row = mysql_fetch_row(db_result))) { - if (mysql_errno(((spider_db_mysql *) db_conn)->db_conn)) + if (mysql_errno(((spider_db_mbase *) db_conn)->db_conn)) { - store_error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn); + store_error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn); my_message(store_error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); } else store_error_num = HA_ERR_END_OF_FILE; DBUG_RETURN(NULL); @@ -587,18 +715,18 @@ SPIDER_DB_ROW *spider_db_mysql_result::fetch_row() DBUG_RETURN((SPIDER_DB_ROW *) &row); } -SPIDER_DB_ROW *spider_db_mysql_result::fetch_row_from_result_buffer( +SPIDER_DB_ROW *spider_db_mbase_result::fetch_row_from_result_buffer( spider_db_result_buffer *spider_res_buf ) { - DBUG_ENTER("spider_db_mysql_result::fetch_row_from_result_buffer"); + DBUG_ENTER("spider_db_mbase_result::fetch_row_from_result_buffer"); DBUG_PRINT("info",("spider this=%p", this)); if (!(row.row = mysql_fetch_row(db_result))) { - if (mysql_errno(((spider_db_mysql *) db_conn)->db_conn)) + if (mysql_errno(((spider_db_mbase *) db_conn)->db_conn)) { - store_error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn); + store_error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn); my_message(store_error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); } else store_error_num = HA_ERR_END_OF_FILE; DBUG_RETURN(NULL); @@ -611,7 +739,7 @@ SPIDER_DB_ROW *spider_db_mysql_result::fetch_row_from_result_buffer( DBUG_RETURN((SPIDER_DB_ROW *) &row); } -SPIDER_DB_ROW *spider_db_mysql_result::fetch_row_from_tmp_table( +SPIDER_DB_ROW *spider_db_mbase_result::fetch_row_from_tmp_table( TABLE *tmp_table ) { uint i; @@ -620,7 +748,7 @@ SPIDER_DB_ROW *spider_db_mysql_result::fetch_row_from_tmp_table( MYSQL_ROW tmp_row; ulong *tmp_lengths; uint field_count; - DBUG_ENTER("spider_db_mysql_result::fetch_row_from_tmp_table"); + DBUG_ENTER("spider_db_mbase_result::fetch_row_from_tmp_table"); DBUG_PRINT("info",("spider this=%p", this)); tmp_str1.init_calc_mem(117); tmp_str2.init_calc_mem(118); @@ -654,7 +782,7 @@ SPIDER_DB_ROW *spider_db_mysql_result::fetch_row_from_tmp_table( DBUG_RETURN((SPIDER_DB_ROW *) &row); } -int spider_db_mysql_result::fetch_table_status( +int spider_db_mbase_result::fetch_table_status( int mode, ha_rows &records, ulong &mean_rec_length, @@ -680,15 +808,15 @@ int spider_db_mysql_result::fetch_table_status( int time_status; #endif long not_used_long; - DBUG_ENTER("spider_db_mysql_result::fetch_table_status"); + DBUG_ENTER("spider_db_mbase_result::fetch_table_status"); DBUG_PRINT("info",("spider this=%p", this)); if (!(mysql_row = mysql_fetch_row(db_result))) { DBUG_PRINT("info",("spider fetch row is null")); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } DBUG_RETURN(ER_SPIDER_REMOTE_TABLE_NOT_FOUND_NUM); @@ -941,21 +1069,21 @@ int spider_db_mysql_result::fetch_table_status( DBUG_RETURN(0); } -int spider_db_mysql_result::fetch_table_records( +int spider_db_mbase_result::fetch_table_records( int mode, ha_rows &records ) { int error_num; MYSQL_ROW mysql_row; - DBUG_ENTER("spider_db_mysql_result::fetch_table_records"); + DBUG_ENTER("spider_db_mbase_result::fetch_table_records"); DBUG_PRINT("info",("spider this=%p", this)); if (!(mysql_row = mysql_fetch_row(db_result))) { DBUG_PRINT("info",("spider fetch row is null")); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } DBUG_RETURN(ER_QUERY_ON_FOREIGN_DATA_SOURCE); @@ -986,7 +1114,7 @@ int spider_db_mysql_result::fetch_table_records( DBUG_RETURN(0); } -int spider_db_mysql_result::fetch_table_cardinality( +int spider_db_mbase_result::fetch_table_cardinality( int mode, TABLE *table, longlong *cardinality, @@ -996,16 +1124,16 @@ int spider_db_mysql_result::fetch_table_cardinality( int error_num; MYSQL_ROW mysql_row; Field *field; - DBUG_ENTER("spider_db_mysql_result::fetch_table_cardinality"); + DBUG_ENTER("spider_db_mbase_result::fetch_table_cardinality"); DBUG_PRINT("info",("spider this=%p", this)); memset((uchar *) cardinality_upd, 0, sizeof(uchar) * bitmap_size); if (!(mysql_row = mysql_fetch_row(db_result))) { DBUG_PRINT("info",("spider fetch row is null")); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } /* no index */ @@ -1074,29 +1202,29 @@ int spider_db_mysql_result::fetch_table_cardinality( mysql_row = mysql_fetch_row(db_result); } } - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } DBUG_RETURN(0); } -int spider_db_mysql_result::fetch_table_mon_status( +int spider_db_mbase_result::fetch_table_mon_status( int &status ) { int error_num; MYSQL_ROW mysql_row; - DBUG_ENTER("spider_db_mysql_result::fetch_table_mon_status"); + DBUG_ENTER("spider_db_mbase_result::fetch_table_mon_status"); DBUG_PRINT("info",("spider this=%p", this)); if (!(mysql_row = mysql_fetch_row(db_result))) { DBUG_PRINT("info",("spider fetch row is null")); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -1115,21 +1243,21 @@ int spider_db_mysql_result::fetch_table_mon_status( DBUG_RETURN(0); } -int spider_db_mysql_result::fetch_show_master_status( +int spider_db_mbase_result::fetch_show_master_status( const char **binlog_file_name, const char **binlog_pos ) { int error_num; MYSQL_ROW mysql_row; - DBUG_ENTER("spider_db_mysql_result::fetch_show_master_status"); + DBUG_ENTER("spider_db_mbase_result::fetch_show_master_status"); DBUG_PRINT("info",("spider this=%p", this)); if (!(mysql_row = mysql_fetch_row(db_result))) { DBUG_PRINT("info",("spider fetch row is null")); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } DBUG_RETURN(ER_QUERY_ON_FOREIGN_DATA_SOURCE); @@ -1146,20 +1274,20 @@ int spider_db_mysql_result::fetch_show_master_status( DBUG_RETURN(0); } -int spider_db_mysql_result::fetch_select_binlog_gtid_pos( +int spider_db_mbase_result::fetch_select_binlog_gtid_pos( const char **gtid_pos ) { int error_num; MYSQL_ROW mysql_row; - DBUG_ENTER("spider_db_mysql_result::fetch_select_binlog_gtid_pos"); + DBUG_ENTER("spider_db_mbase_result::fetch_select_binlog_gtid_pos"); DBUG_PRINT("info",("spider this=%p", this)); if (!(mysql_row = mysql_fetch_row(db_result))) { DBUG_PRINT("info",("spider fetch row is null")); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } DBUG_RETURN(ER_QUERY_ON_FOREIGN_DATA_SOURCE); @@ -1174,24 +1302,24 @@ int spider_db_mysql_result::fetch_select_binlog_gtid_pos( DBUG_RETURN(0); } -longlong spider_db_mysql_result::num_rows() +longlong spider_db_mbase_result::num_rows() { - DBUG_ENTER("spider_db_mysql_result::num_rows"); + DBUG_ENTER("spider_db_mbase_result::num_rows"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN((longlong) mysql_num_rows(db_result)); } -uint spider_db_mysql_result::num_fields() +uint spider_db_mbase_result::num_fields() { - DBUG_ENTER("spider_db_mysql_result::num_fields"); + DBUG_ENTER("spider_db_mbase_result::num_fields"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(mysql_num_fields(db_result)); } -void spider_db_mysql_result::move_to_pos( +void spider_db_mbase_result::move_to_pos( longlong pos ) { - DBUG_ENTER("spider_db_mysql_result::move_to_pos"); + DBUG_ENTER("spider_db_mbase_result::move_to_pos"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider pos=%lld", pos)); /* @@ -1201,31 +1329,31 @@ void spider_db_mysql_result::move_to_pos( DBUG_VOID_RETURN; } -int spider_db_mysql_result::get_errno() +int spider_db_mbase_result::get_errno() { - DBUG_ENTER("spider_db_mysql_result::get_errno"); + DBUG_ENTER("spider_db_mbase_result::get_errno"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider store_error_num=%d", store_error_num)); DBUG_RETURN(store_error_num); } #ifdef SPIDER_HAS_DISCOVER_TABLE_STRUCTURE -int spider_db_mysql_result::fetch_columns_for_discover_table_structure( +int spider_db_mbase_result::fetch_columns_for_discover_table_structure( spider_string *str, CHARSET_INFO *access_charset ) { int error_num; uint length; MYSQL_ROW mysql_row; - DBUG_ENTER("spider_db_mysql_result::fetch_columns_for_discover_table_structure"); + DBUG_ENTER("spider_db_mbase_result::fetch_columns_for_discover_table_structure"); DBUG_PRINT("info",("spider this=%p", this)); if (!(mysql_row = mysql_fetch_row(db_result))) { DBUG_PRINT("info",("spider fetch row is null")); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -1327,30 +1455,30 @@ int spider_db_mysql_result::fetch_columns_for_discover_table_structure( } str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN); } while ((mysql_row = mysql_fetch_row(db_result))); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } DBUG_RETURN(0); } -int spider_db_mysql_result::fetch_index_for_discover_table_structure( +int spider_db_mbase_result::fetch_index_for_discover_table_structure( spider_string *str, CHARSET_INFO *access_charset ) { int error_num; MYSQL_ROW mysql_row; - DBUG_ENTER("spider_db_mysql_result::fetch_index_for_discover_table_structure"); + DBUG_ENTER("spider_db_mbase_result::fetch_index_for_discover_table_structure"); DBUG_PRINT("info",("spider this=%p", this)); if (!(mysql_row = mysql_fetch_row(db_result))) { DBUG_PRINT("info",("spider fetch row is null")); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } DBUG_RETURN(0); @@ -1519,10 +1647,10 @@ int spider_db_mysql_result::fetch_index_for_discover_table_structure( else using_hash = FALSE; } while ((mysql_row = mysql_fetch_row(db_result))); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } if (!first) @@ -1540,22 +1668,22 @@ int spider_db_mysql_result::fetch_index_for_discover_table_structure( DBUG_RETURN(0); } -int spider_db_mysql_result::fetch_table_for_discover_table_structure( +int spider_db_mbase_result::fetch_table_for_discover_table_structure( spider_string *str, SPIDER_SHARE *spider_share, CHARSET_INFO *access_charset ) { int error_num; MYSQL_ROW mysql_row; - DBUG_ENTER("spider_db_mysql_result::fetch_table_for_discover_table_structure"); + DBUG_ENTER("spider_db_mbase_result::fetch_table_for_discover_table_structure"); DBUG_PRINT("info",("spider this=%p", this)); if (!(mysql_row = mysql_fetch_row(db_result))) { DBUG_PRINT("info",("spider fetch row is null")); - if ((error_num = mysql_errno(((spider_db_mysql *) db_conn)->db_conn))) + if ((error_num = mysql_errno(((spider_db_mbase *) db_conn)->db_conn))) { my_message(error_num, - mysql_error(((spider_db_mysql *) db_conn)->db_conn), MYF(0)); + mysql_error(((spider_db_mbase *) db_conn)->db_conn), MYF(0)); DBUG_RETURN(error_num); } DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -1581,20 +1709,39 @@ int spider_db_mysql_result::fetch_table_for_discover_table_structure( } #endif -spider_db_mysql::spider_db_mysql( - SPIDER_CONN *conn -) : spider_db_conn(conn), lock_table_hash_inited(FALSE), - handler_open_array_inited(FALSE) +spider_db_mbase::spider_db_mbase( + SPIDER_CONN *conn, + spider_db_mbase_util *spider_db_mbase_utility +) : spider_db_conn(conn), spider_db_mbase_utility(spider_db_mbase_utility), + lock_table_hash_inited(FALSE), handler_open_array_inited(FALSE) { - DBUG_ENTER("spider_db_mysql::spider_db_mysql"); + DBUG_ENTER("spider_db_mbase::spider_db_mbase"); DBUG_PRINT("info",("spider this=%p", this)); db_conn = NULL; DBUG_VOID_RETURN; } -spider_db_mysql::~spider_db_mysql() +spider_db_mysql::spider_db_mysql( + SPIDER_CONN *conn +) : spider_db_mbase(conn, &spider_db_mysql_utility) { - DBUG_ENTER("spider_db_mysql::~spider_db_mysql"); + DBUG_ENTER("spider_db_mysql::spider_db_mysql"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mariadb::spider_db_mariadb( + SPIDER_CONN *conn +) : spider_db_mbase(conn, &spider_db_mariadb_utility) +{ + DBUG_ENTER("spider_db_mariadb::spider_db_mariadb"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mbase::~spider_db_mbase() +{ + DBUG_ENTER("spider_db_mbase::~spider_db_mbase"); DBUG_PRINT("info",("spider this=%p", this)); if (handler_open_array_inited) { @@ -1616,9 +1763,23 @@ spider_db_mysql::~spider_db_mysql() DBUG_VOID_RETURN; } -int spider_db_mysql::init() +spider_db_mysql::~spider_db_mysql() { - DBUG_ENTER("spider_db_mysql::init"); + DBUG_ENTER("spider_db_mysql::~spider_db_mysql"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mariadb::~spider_db_mariadb() +{ + DBUG_ENTER("spider_db_mariadb::~spider_db_mariadb"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +int spider_db_mbase::init() +{ + DBUG_ENTER("spider_db_mbase::init"); DBUG_PRINT("info",("spider this=%p", this)); if ( my_hash_init(&lock_table_hash, spd_charset_utf8_bin, 32, 0, 0, @@ -1648,21 +1809,21 @@ int spider_db_mysql::init() DBUG_RETURN(0); } -bool spider_db_mysql::is_connected() +bool spider_db_mbase::is_connected() { - DBUG_ENTER("spider_db_mysql::is_connected"); + DBUG_ENTER("spider_db_mbase::is_connected"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(db_conn); } -void spider_db_mysql::bg_connect() +void spider_db_mbase::bg_connect() { - DBUG_ENTER("spider_db_mysql::bg_connect"); + DBUG_ENTER("spider_db_mbase::bg_connect"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_VOID_RETURN; } -int spider_db_mysql::connect( +int spider_db_mbase::connect( char *tgt_host, char *tgt_username, char *tgt_password, @@ -1674,7 +1835,7 @@ int spider_db_mysql::connect( ) { int error_num; my_bool connect_mutex = spider_param_connect_mutex(); - DBUG_ENTER("spider_db_mysql::connect"); + DBUG_ENTER("spider_db_mbase::connect"); DBUG_PRINT("info",("spider this=%p", this)); while (TRUE) { @@ -1795,25 +1956,25 @@ int spider_db_mysql::connect( DBUG_RETURN(0); } -int spider_db_mysql::ping( +int spider_db_mbase::ping( ) { - DBUG_ENTER("spider_db_mysql::ping"); + DBUG_ENTER("spider_db_mbase::ping"); DBUG_PRINT("info",("spider this=%p", this)); if (spider_param_dry_access()) DBUG_RETURN(0); DBUG_RETURN(simple_command(db_conn, COM_PING, 0, 0, 0)); } -void spider_db_mysql::bg_disconnect() +void spider_db_mbase::bg_disconnect() { - DBUG_ENTER("spider_db_mysql::bg_disconnect"); + DBUG_ENTER("spider_db_mbase::bg_disconnect"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_VOID_RETURN; } -void spider_db_mysql::disconnect() +void spider_db_mbase::disconnect() { - DBUG_ENTER("spider_db_mysql::disconnect"); + DBUG_ENTER("spider_db_mbase::disconnect"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider db_conn=%p", db_conn)); if (db_conn) @@ -1824,9 +1985,9 @@ void spider_db_mysql::disconnect() DBUG_VOID_RETURN; } -int spider_db_mysql::set_net_timeout() +int spider_db_mbase::set_net_timeout() { - DBUG_ENTER("spider_db_mysql::set_net_timeout"); + DBUG_ENTER("spider_db_mbase::set_net_timeout"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider conn=%p", conn)); my_net_set_read_timeout(&db_conn->net, conn->net_read_timeout); @@ -1834,14 +1995,14 @@ int spider_db_mysql::set_net_timeout() DBUG_RETURN(0); } -int spider_db_mysql::exec_query( +int spider_db_mbase::exec_query( const char *query, uint length, int quick_mode ) { int error_num = 0; uint log_result_errors = spider_param_log_result_errors(); - DBUG_ENTER("spider_db_mysql::exec_query"); + DBUG_ENTER("spider_db_mbase::exec_query"); DBUG_PRINT("info",("spider this=%p", this)); if (spider_param_general_log()) { @@ -1945,30 +2106,30 @@ int spider_db_mysql::exec_query( DBUG_RETURN(error_num); } -int spider_db_mysql::get_errno() +int spider_db_mbase::get_errno() { - DBUG_ENTER("spider_db_mysql::get_errno"); + DBUG_ENTER("spider_db_mbase::get_errno"); DBUG_PRINT("info",("spider this=%p", this)); stored_error = mysql_errno(db_conn); DBUG_PRINT("info",("spider stored_error=%d", stored_error)); DBUG_RETURN(stored_error); } -const char *spider_db_mysql::get_error() +const char *spider_db_mbase::get_error() { const char *error_ptr; - DBUG_ENTER("spider_db_mysql::get_error"); + DBUG_ENTER("spider_db_mbase::get_error"); DBUG_PRINT("info",("spider this=%p", this)); error_ptr = mysql_error(db_conn); DBUG_PRINT("info",("spider error=%s", error_ptr)); DBUG_RETURN(error_ptr); } -bool spider_db_mysql::is_server_gone_error( +bool spider_db_mbase::is_server_gone_error( int error_num ) { bool server_gone; - DBUG_ENTER("spider_db_mysql::is_server_gone_error"); + DBUG_ENTER("spider_db_mbase::is_server_gone_error"); DBUG_PRINT("info",("spider this=%p", this)); server_gone = (error_num == CR_SERVER_GONE_ERROR || error_num == CR_SERVER_LOST); @@ -1976,11 +2137,11 @@ bool spider_db_mysql::is_server_gone_error( DBUG_RETURN(server_gone); } -bool spider_db_mysql::is_dup_entry_error( +bool spider_db_mbase::is_dup_entry_error( int error_num ) { bool dup_entry; - DBUG_ENTER("spider_db_mysql::is_dup_entry_error"); + DBUG_ENTER("spider_db_mbase::is_dup_entry_error"); DBUG_PRINT("info",("spider this=%p", this)); dup_entry = ( @@ -1992,11 +2153,11 @@ bool spider_db_mysql::is_dup_entry_error( DBUG_RETURN(dup_entry); } -bool spider_db_mysql::is_xa_nota_error( +bool spider_db_mbase::is_xa_nota_error( int error_num ) { bool xa_nota; - DBUG_ENTER("spider_db_mysql::is_xa_nota_error"); + DBUG_ENTER("spider_db_mbase::is_xa_nota_error"); DBUG_PRINT("info",("spider this=%p", this)); xa_nota = ( @@ -2008,10 +2169,10 @@ bool spider_db_mysql::is_xa_nota_error( DBUG_RETURN(xa_nota); } -void spider_db_mysql::print_warnings( +void spider_db_mbase::print_warnings( struct tm *l_time ) { - DBUG_ENTER("spider_db_mysql::print_warnings"); + DBUG_ENTER("spider_db_mbase::print_warnings"); DBUG_PRINT("info",("spider this=%p", this)); if (db_conn->status == MYSQL_STATUS_READY) { @@ -2083,16 +2244,16 @@ void spider_db_mysql::print_warnings( DBUG_VOID_RETURN; } -spider_db_result *spider_db_mysql::store_result( +spider_db_result *spider_db_mbase::store_result( spider_db_result_buffer **spider_res_buf, st_spider_db_request_key *request_key, int *error_num ) { - spider_db_mysql_result *result; - DBUG_ENTER("spider_db_mysql::store_result"); + spider_db_mbase_result *result; + DBUG_ENTER("spider_db_mbase::store_result"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(!spider_res_buf); - if ((result = new spider_db_mysql_result(this))) + if ((result = new spider_db_mbase_result(this))) { *error_num = 0; if ( @@ -2111,14 +2272,14 @@ spider_db_result *spider_db_mysql::store_result( DBUG_RETURN(result); } -spider_db_result *spider_db_mysql::use_result( +spider_db_result *spider_db_mbase::use_result( st_spider_db_request_key *request_key, int *error_num ) { - spider_db_mysql_result *result; - DBUG_ENTER("spider_db_mysql::use_result"); + spider_db_mbase_result *result; + DBUG_ENTER("spider_db_mbase::use_result"); DBUG_PRINT("info",("spider this=%p", this)); - if ((result = new spider_db_mysql_result(this))) + if ((result = new spider_db_mbase_result(this))) { *error_num = 0; if ( @@ -2136,10 +2297,10 @@ spider_db_result *spider_db_mysql::use_result( DBUG_RETURN(result); } -int spider_db_mysql::next_result() +int spider_db_mbase::next_result() { int status; - DBUG_ENTER("spider_db_mysql::next_result"); + DBUG_ENTER("spider_db_mbase::next_result"); DBUG_PRINT("info",("spider this=%p", this)); if (db_conn->status != MYSQL_STATUS_READY) { @@ -2165,10 +2326,10 @@ int spider_db_mysql::next_result() DBUG_RETURN(-1); } -uint spider_db_mysql::affected_rows() +uint spider_db_mbase::affected_rows() { MYSQL *last_used_con; - DBUG_ENTER("spider_db_mysql::affected_rows"); + DBUG_ENTER("spider_db_mbase::affected_rows"); DBUG_PRINT("info",("spider this=%p", this)); #if MYSQL_VERSION_ID < 50500 last_used_con = db_conn->last_used_con; @@ -2178,10 +2339,10 @@ uint spider_db_mysql::affected_rows() DBUG_RETURN((uint) last_used_con->affected_rows); } -ulonglong spider_db_mysql::last_insert_id() +ulonglong spider_db_mbase::last_insert_id() { MYSQL *last_used_con; - DBUG_ENTER("spider_db_mysql::last_insert_id"); + DBUG_ENTER("spider_db_mbase::last_insert_id"); DBUG_PRINT("info",("spider this=%p", this)); #if MYSQL_VERSION_ID < 50500 last_used_con = db_conn->last_used_con; @@ -2191,30 +2352,30 @@ ulonglong spider_db_mysql::last_insert_id() DBUG_RETURN((uint) last_used_con->insert_id); } -int spider_db_mysql::set_character_set( +int spider_db_mbase::set_character_set( const char *csname ) { - DBUG_ENTER("spider_db_mysql::set_character_set"); + DBUG_ENTER("spider_db_mbase::set_character_set"); DBUG_PRINT("info",("spider this=%p", this)); if (spider_param_dry_access()) DBUG_RETURN(0); DBUG_RETURN(mysql_set_character_set(db_conn, csname)); } -int spider_db_mysql::select_db( +int spider_db_mbase::select_db( const char *dbname ) { - DBUG_ENTER("spider_db_mysql::select_db"); + DBUG_ENTER("spider_db_mbase::select_db"); DBUG_PRINT("info",("spider this=%p", this)); if (spider_param_dry_access()) DBUG_RETURN(0); DBUG_RETURN(mysql_select_db(db_conn, dbname)); } -int spider_db_mysql::consistent_snapshot( +int spider_db_mbase::consistent_snapshot( int *need_mon ) { - DBUG_ENTER("spider_db_mysql::consistent_snapshot"); + DBUG_ENTER("spider_db_mbase::consistent_snapshot"); DBUG_PRINT("info",("spider this=%p", this)); if (spider_db_query( conn, @@ -2229,17 +2390,17 @@ int spider_db_mysql::consistent_snapshot( DBUG_RETURN(0); } -bool spider_db_mysql::trx_start_in_bulk_sql() +bool spider_db_mbase::trx_start_in_bulk_sql() { - DBUG_ENTER("spider_db_mysql::trx_start_in_bulk_sql"); + DBUG_ENTER("spider_db_mbase::trx_start_in_bulk_sql"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(TRUE); } -int spider_db_mysql::start_transaction( +int spider_db_mbase::start_transaction( int *need_mon ) { - DBUG_ENTER("spider_db_mysql::start_transaction"); + DBUG_ENTER("spider_db_mbase::start_transaction"); DBUG_PRINT("info",("spider this=%p", this)); if (spider_db_query( conn, @@ -2254,10 +2415,10 @@ int spider_db_mysql::start_transaction( DBUG_RETURN(0); } -int spider_db_mysql::commit( +int spider_db_mbase::commit( int *need_mon ) { - DBUG_ENTER("spider_db_mysql::commit"); + DBUG_ENTER("spider_db_mbase::commit"); DBUG_PRINT("info",("spider this=%p", this)); if (spider_db_query( conn, @@ -2272,12 +2433,12 @@ int spider_db_mysql::commit( DBUG_RETURN(0); } -int spider_db_mysql::rollback( +int spider_db_mbase::rollback( int *need_mon ) { bool is_error; int error_num; - DBUG_ENTER("spider_db_mysql::rollback"); + DBUG_ENTER("spider_db_mbase::rollback"); DBUG_PRINT("info",("spider this=%p", this)); conn->mta_conn_mutex_unlock_later = TRUE; if (spider_db_query( @@ -2307,30 +2468,30 @@ int spider_db_mysql::rollback( DBUG_RETURN(0); } -int spider_db_mysql::xa_start( +int spider_db_mbase::xa_start( XID *xid, int *need_mon ) { - DBUG_ENTER("spider_db_mysql::xa_start"); + DBUG_ENTER("spider_db_mbase::xa_start"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_RETURN(0); } -bool spider_db_mysql::xa_start_in_bulk_sql() +bool spider_db_mbase::xa_start_in_bulk_sql() { - DBUG_ENTER("spider_db_mysql::xa_start_in_bulk_sql"); + DBUG_ENTER("spider_db_mbase::xa_start_in_bulk_sql"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(TRUE); } -int spider_db_mysql::xa_end( +int spider_db_mbase::xa_end( XID *xid, int *need_mon ) { char sql_buf[SPIDER_SQL_XA_END_LEN + XIDDATASIZE + sizeof(long) + 9]; spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); - DBUG_ENTER("spider_db_mysql::xa_end"); + DBUG_ENTER("spider_db_mbase::xa_end"); DBUG_PRINT("info",("spider this=%p", this)); sql_str.init_calc_mem(108); @@ -2350,13 +2511,13 @@ int spider_db_mysql::xa_end( DBUG_RETURN(0); } -int spider_db_mysql::xa_prepare( +int spider_db_mbase::xa_prepare( XID *xid, int *need_mon ) { char sql_buf[SPIDER_SQL_XA_PREPARE_LEN + XIDDATASIZE + sizeof(long) + 9]; spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); - DBUG_ENTER("spider_db_mysql::xa_prepare"); + DBUG_ENTER("spider_db_mbase::xa_prepare"); DBUG_PRINT("info",("spider this=%p", this)); sql_str.init_calc_mem(109); @@ -2376,13 +2537,13 @@ int spider_db_mysql::xa_prepare( DBUG_RETURN(0); } -int spider_db_mysql::xa_commit( +int spider_db_mbase::xa_commit( XID *xid, int *need_mon ) { char sql_buf[SPIDER_SQL_XA_COMMIT_LEN + XIDDATASIZE + sizeof(long) + 9]; spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); - DBUG_ENTER("spider_db_mysql::xa_commit"); + DBUG_ENTER("spider_db_mbase::xa_commit"); DBUG_PRINT("info",("spider this=%p", this)); sql_str.init_calc_mem(110); @@ -2402,13 +2563,13 @@ int spider_db_mysql::xa_commit( DBUG_RETURN(0); } -int spider_db_mysql::xa_rollback( +int spider_db_mbase::xa_rollback( XID *xid, int *need_mon ) { char sql_buf[SPIDER_SQL_XA_ROLLBACK_LEN + XIDDATASIZE + sizeof(long) + 9]; spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); - DBUG_ENTER("spider_db_mysql::xa_rollback"); + DBUG_ENTER("spider_db_mbase::xa_rollback"); DBUG_PRINT("info",("spider this=%p", this)); sql_str.init_calc_mem(111); @@ -2428,18 +2589,18 @@ int spider_db_mysql::xa_rollback( DBUG_RETURN(0); } -bool spider_db_mysql::set_trx_isolation_in_bulk_sql() +bool spider_db_mbase::set_trx_isolation_in_bulk_sql() { - DBUG_ENTER("spider_db_mysql::set_trx_isolation_in_bulk_sql"); + DBUG_ENTER("spider_db_mbase::set_trx_isolation_in_bulk_sql"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(TRUE); } -int spider_db_mysql::set_trx_isolation( +int spider_db_mbase::set_trx_isolation( int trx_isolation, int *need_mon ) { - DBUG_ENTER("spider_db_mysql::set_trx_isolation"); + DBUG_ENTER("spider_db_mbase::set_trx_isolation"); DBUG_PRINT("info",("spider this=%p", this)); switch (trx_isolation) { @@ -2497,18 +2658,18 @@ int spider_db_mysql::set_trx_isolation( DBUG_RETURN(0); } -bool spider_db_mysql::set_autocommit_in_bulk_sql() +bool spider_db_mbase::set_autocommit_in_bulk_sql() { - DBUG_ENTER("spider_db_mysql::set_autocommit_in_bulk_sql"); + DBUG_ENTER("spider_db_mbase::set_autocommit_in_bulk_sql"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(TRUE); } -int spider_db_mysql::set_autocommit( +int spider_db_mbase::set_autocommit( bool autocommit, int *need_mon ) { - DBUG_ENTER("spider_db_mysql::set_autocommit"); + DBUG_ENTER("spider_db_mbase::set_autocommit"); DBUG_PRINT("info",("spider this=%p", this)); if (autocommit) { @@ -2537,18 +2698,18 @@ int spider_db_mysql::set_autocommit( DBUG_RETURN(0); } -bool spider_db_mysql::set_sql_log_off_in_bulk_sql() +bool spider_db_mbase::set_sql_log_off_in_bulk_sql() { - DBUG_ENTER("spider_db_mysql::set_sql_log_off_in_bulk_sql"); + DBUG_ENTER("spider_db_mbase::set_sql_log_off_in_bulk_sql"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(TRUE); } -int spider_db_mysql::set_sql_log_off( +int spider_db_mbase::set_sql_log_off( bool sql_log_off, int *need_mon ) { - DBUG_ENTER("spider_db_mysql::set_sql_log_off"); + DBUG_ENTER("spider_db_mbase::set_sql_log_off"); DBUG_PRINT("info",("spider this=%p", this)); if (sql_log_off) { @@ -2577,21 +2738,21 @@ int spider_db_mysql::set_sql_log_off( DBUG_RETURN(0); } -bool spider_db_mysql::set_time_zone_in_bulk_sql() +bool spider_db_mbase::set_time_zone_in_bulk_sql() { - DBUG_ENTER("spider_db_mysql::set_time_zone_in_bulk_sql"); + DBUG_ENTER("spider_db_mbase::set_time_zone_in_bulk_sql"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(TRUE); } -int spider_db_mysql::set_time_zone( +int spider_db_mbase::set_time_zone( Time_zone *time_zone, int *need_mon ) { const String *tz_str = time_zone->get_name(); char sql_buf[MAX_FIELD_WIDTH]; spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); - DBUG_ENTER("spider_db_mysql::set_time_zone"); + DBUG_ENTER("spider_db_mbase::set_time_zone"); DBUG_PRINT("info",("spider this=%p", this)); sql_str.init_calc_mem(214); sql_str.length(0); @@ -2614,7 +2775,7 @@ int spider_db_mysql::set_time_zone( DBUG_RETURN(0); } -int spider_db_mysql::exec_simple_sql_with_result( +int spider_db_mbase::exec_simple_sql_with_result( SPIDER_TRX *trx, SPIDER_SHARE *share, const char *sql, @@ -2624,7 +2785,7 @@ int spider_db_mysql::exec_simple_sql_with_result( SPIDER_DB_RESULT **res ) { int error_num; - DBUG_ENTER("spider_db_mysql::exec_simple_sql_with_result"); + DBUG_ENTER("spider_db_mbase::exec_simple_sql_with_result"); pthread_mutex_lock(&conn->mta_conn_mutex); SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos); conn->need_mon = need_mon; @@ -2714,7 +2875,7 @@ int spider_db_mysql::exec_simple_sql_with_result( DBUG_RETURN(0); } -int spider_db_mysql::show_master_status( +int spider_db_mbase::show_master_status( SPIDER_TRX *trx, SPIDER_SHARE *share, int all_link_idx, @@ -2728,7 +2889,7 @@ int spider_db_mysql::show_master_status( int error_num; const char *binlog_file_name, *binlog_pos; uint binlog_file_name_length, binlog_pos_length; - DBUG_ENTER("spider_db_mysql::show_master_status"); + DBUG_ENTER("spider_db_mbase::show_master_status"); if ((error_num = exec_simple_sql_with_result(trx, share, SPIDER_SQL_SHOW_MASTER_STATUS_STR, SPIDER_SQL_SHOW_MASTER_STATUS_LEN, all_link_idx, need_mon, res1)) @@ -2737,7 +2898,7 @@ int spider_db_mysql::show_master_status( DBUG_RETURN(error_num); } - if (!(error_num = ((spider_db_mysql_result *)*res1)->fetch_show_master_status( + if (!(error_num = ((spider_db_mbase_result *)*res1)->fetch_show_master_status( &binlog_file_name, &binlog_pos)) ) { binlog_file_name_length = strlen(binlog_file_name); @@ -2776,7 +2937,7 @@ int spider_db_mysql::show_master_status( DBUG_RETURN(0); } -int spider_db_mysql::select_binlog_gtid_pos( +int spider_db_mbase::select_binlog_gtid_pos( SPIDER_TRX *trx, SPIDER_SHARE *share, int all_link_idx, @@ -2792,7 +2953,7 @@ int spider_db_mysql::select_binlog_gtid_pos( int error_num; size_t length; const char *gtid_pos; - DBUG_ENTER("spider_db_mysql::select_binlog_gtid_pos"); + DBUG_ENTER("spider_db_mbase::select_binlog_gtid_pos"); str->length(0); if (str->reserve( SPIDER_SQL_BINLOG_GTID_POS_LEN + @@ -2829,7 +2990,7 @@ int spider_db_mysql::select_binlog_gtid_pos( DBUG_PRINT("info", ("spider error_num=%d 1", error_num)); DBUG_RETURN(error_num); } - if (!(error_num = ((spider_db_mysql_result *)*res)->fetch_select_binlog_gtid_pos(>id_pos))) + if (!(error_num = ((spider_db_mbase_result *)*res)->fetch_select_binlog_gtid_pos(>id_pos))) { spider_store_binlog_pos_gtid(table, gtid_pos, strlen(gtid_pos), conn->access_charset); } @@ -2846,18 +3007,18 @@ int spider_db_mysql::select_binlog_gtid_pos( } #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) -int spider_db_mysql::append_sql( +int spider_db_mbase::append_sql( char *sql, ulong sql_length, st_spider_db_request_key *request_key ) { - DBUG_ENTER("spider_db_mysql::append_sql"); + DBUG_ENTER("spider_db_mbase::append_sql"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_RETURN(0); } -int spider_db_mysql::append_open_handler( +int spider_db_mbase::append_open_handler( uint handler_id, const char *db_name, const char *table_name, @@ -2865,13 +3026,13 @@ int spider_db_mysql::append_open_handler( const char *sql, st_spider_db_request_key *request_key ) { - DBUG_ENTER("spider_db_mysql::append_open_handler"); + DBUG_ENTER("spider_db_mbase::append_open_handler"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_RETURN(0); } -int spider_db_mysql::append_select( +int spider_db_mbase::append_select( uint handler_id, spider_string *sql, SPIDER_DB_HS_STRING_REF_BUFFER *keys, @@ -2879,24 +3040,24 @@ int spider_db_mysql::append_select( int skip, st_spider_db_request_key *request_key ) { - DBUG_ENTER("spider_db_mysql::append_select"); + DBUG_ENTER("spider_db_mbase::append_select"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_RETURN(0); } -int spider_db_mysql::append_insert( +int spider_db_mbase::append_insert( uint handler_id, SPIDER_DB_HS_STRING_REF_BUFFER *upds, st_spider_db_request_key *request_key ) { - DBUG_ENTER("spider_db_mysql::append_insert"); + DBUG_ENTER("spider_db_mbase::append_insert"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_RETURN(0); } -int spider_db_mysql::append_update( +int spider_db_mbase::append_update( uint handler_id, spider_string *sql, SPIDER_DB_HS_STRING_REF_BUFFER *keys, @@ -2907,13 +3068,13 @@ int spider_db_mysql::append_update( bool decrement, st_spider_db_request_key *request_key ) { - DBUG_ENTER("spider_db_mysql::append_update"); + DBUG_ENTER("spider_db_mbase::append_update"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_RETURN(0); } -int spider_db_mysql::append_delete( +int spider_db_mbase::append_delete( uint handler_id, spider_string *sql, SPIDER_DB_HS_STRING_REF_BUFFER *keys, @@ -2921,27 +3082,27 @@ int spider_db_mysql::append_delete( int skip, st_spider_db_request_key *request_key ) { - DBUG_ENTER("spider_db_mysql::append_delete"); + DBUG_ENTER("spider_db_mbase::append_delete"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_RETURN(0); } -void spider_db_mysql::reset_request_queue() +void spider_db_mbase::reset_request_queue() { - DBUG_ENTER("spider_db_mysql::reset_request_queue"); + DBUG_ENTER("spider_db_mbase::reset_request_queue"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_VOID_RETURN; } #endif -size_t spider_db_mysql::escape_string( +size_t spider_db_mbase::escape_string( char *to, const char *from, size_t from_length ) { - DBUG_ENTER("spider_db_mysql::escape_string"); + DBUG_ENTER("spider_db_mbase::escape_string"); DBUG_PRINT("info",("spider this=%p", this)); if (db_conn->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) DBUG_RETURN(escape_quotes_for_mysql(db_conn->charset, to, 0, @@ -2950,14 +3111,14 @@ size_t spider_db_mysql::escape_string( from, from_length)); } -bool spider_db_mysql::have_lock_table_list() +bool spider_db_mbase::have_lock_table_list() { - DBUG_ENTER("spider_db_mysql::have_lock_table_list"); + DBUG_ENTER("spider_db_mbase::have_lock_table_list"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(lock_table_hash.records); } -int spider_db_mysql::append_lock_tables( +int spider_db_mbase::append_lock_tables( spider_string *str ) { int error_num; @@ -2972,9 +3133,9 @@ int spider_db_mysql::append_lock_tables( const char *table_name; uint table_name_length; CHARSET_INFO *table_name_charset; - DBUG_ENTER("spider_db_mysql::lock_tables"); + DBUG_ENTER("spider_db_mbase::lock_tables"); DBUG_PRINT("info",("spider this=%p", this)); - if ((error_num = spider_db_mysql_utility.append_lock_table_head(str))) + if ((error_num = spider_db_mbase_utility->append_lock_table_head(str))) { DBUG_RETURN(error_num); } @@ -3003,7 +3164,7 @@ int spider_db_mysql::append_lock_tables( DBUG_RETURN(0); } conn_link_idx = tmp_spider->conn_link_idx[tmp_link_idx]; - spider_mysql_share *db_share = (spider_mysql_share *) + spider_mbase_share *db_share = (spider_mbase_share *) tmp_spider->share->dbton_share[conn->dbton_id]; if (&db_share->db_names_str[conn_link_idx]) { @@ -3026,7 +3187,7 @@ int spider_db_mysql::append_lock_tables( tmp_spider->share->tgt_table_names_lengths[conn_link_idx]; table_name_charset = system_charset_info; } - if ((error_num = spider_db_mysql_utility. + if ((error_num = spider_db_mbase_utility-> append_lock_table_body( str, db_name, @@ -3048,54 +3209,54 @@ int spider_db_mysql::append_lock_tables( my_hash_delete(&lock_table_hash, (uchar*) tmp_link_for_hash); #endif } - if ((error_num = spider_db_mysql_utility.append_lock_table_tail(str))) + if ((error_num = spider_db_mbase_utility->append_lock_table_tail(str))) { DBUG_RETURN(error_num); } DBUG_RETURN(0); } -int spider_db_mysql::append_unlock_tables( +int spider_db_mbase::append_unlock_tables( spider_string *str ) { int error_num; - DBUG_ENTER("spider_db_mysql::append_unlock_tables"); + DBUG_ENTER("spider_db_mbase::append_unlock_tables"); DBUG_PRINT("info",("spider this=%p", this)); - if ((error_num = spider_db_mysql_utility.append_unlock_table(str))) + if ((error_num = spider_db_mbase_utility->append_unlock_table(str))) { DBUG_RETURN(error_num); } DBUG_RETURN(0); } -uint spider_db_mysql::get_lock_table_hash_count() +uint spider_db_mbase::get_lock_table_hash_count() { - DBUG_ENTER("spider_db_mysql::get_lock_table_hash_count"); + DBUG_ENTER("spider_db_mbase::get_lock_table_hash_count"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(lock_table_hash.records); } -void spider_db_mysql::reset_lock_table_hash() +void spider_db_mbase::reset_lock_table_hash() { - DBUG_ENTER("spider_db_mysql::reset_lock_table_hash"); + DBUG_ENTER("spider_db_mbase::reset_lock_table_hash"); DBUG_PRINT("info",("spider this=%p", this)); my_hash_reset(&lock_table_hash); DBUG_VOID_RETURN; } -uint spider_db_mysql::get_opened_handler_count() +uint spider_db_mbase::get_opened_handler_count() { - DBUG_ENTER("spider_db_mysql::get_opened_handler_count"); + DBUG_ENTER("spider_db_mbase::get_opened_handler_count"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(handler_open_array.elements); } -void spider_db_mysql::reset_opened_handler() +void spider_db_mbase::reset_opened_handler() { ha_spider *tmp_spider; int tmp_link_idx; SPIDER_LINK_FOR_HASH **tmp_link_for_hash; - DBUG_ENTER("spider_db_mysql::reset_opened_handler"); + DBUG_ENTER("spider_db_mbase::reset_opened_handler"); DBUG_PRINT("info",("spider this=%p", this)); while ((tmp_link_for_hash = (SPIDER_LINK_FOR_HASH **) pop_dynamic(&handler_open_array))) @@ -3107,7 +3268,7 @@ void spider_db_mysql::reset_opened_handler() DBUG_VOID_RETURN; } -void spider_db_mysql::set_dup_key_idx( +void spider_db_mbase::set_dup_key_idx( ha_spider *spider, int link_idx ) { @@ -3116,7 +3277,7 @@ void spider_db_mysql::set_dup_key_idx( int key_name_length; int max_length = 0; const char *key_name; - DBUG_ENTER("spider_db_mysql::set_dup_key_idx"); + DBUG_ENTER("spider_db_mbase::set_dup_key_idx"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider error_str=%s", conn->error_str)); for (roop_count = 0; roop_count < table->s->keys; roop_count++) @@ -3156,21 +3317,42 @@ void spider_db_mysql::set_dup_key_idx( DBUG_VOID_RETURN; } -bool spider_db_mysql::cmp_request_key_to_snd( +bool spider_db_mbase::cmp_request_key_to_snd( st_spider_db_request_key *request_key ) { - DBUG_ENTER("spider_db_mysql::cmp_request_key_to_snd"); + DBUG_ENTER("spider_db_mbase::cmp_request_key_to_snd"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(TRUE); } -spider_db_mysql_util::spider_db_mysql_util() : spider_db_util() +spider_db_mbase_util::spider_db_mbase_util() : spider_db_util() +{ + DBUG_ENTER("spider_db_mbase_util::spider_db_mbase_util"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mysql_util::spider_db_mysql_util() : spider_db_mbase_util() { DBUG_ENTER("spider_db_mysql_util::spider_db_mysql_util"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_VOID_RETURN; } +spider_db_mariadb_util::spider_db_mariadb_util() : spider_db_mbase_util() +{ + DBUG_ENTER("spider_db_mariadb_util::spider_db_mariadb_util"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_db_mbase_util::~spider_db_mbase_util() +{ + DBUG_ENTER("spider_db_mbase_util::~spider_db_mbase_util"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + spider_db_mysql_util::~spider_db_mysql_util() { DBUG_ENTER("spider_db_mysql_util::~spider_db_mysql_util"); @@ -3178,25 +3360,32 @@ spider_db_mysql_util::~spider_db_mysql_util() DBUG_VOID_RETURN; } -int spider_db_mysql_util::append_name( +spider_db_mariadb_util::~spider_db_mariadb_util() +{ + DBUG_ENTER("spider_db_mariadb_util::~spider_db_mariadb_util"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +int spider_db_mbase_util::append_name( spider_string *str, const char *name, uint name_length ) { - DBUG_ENTER("spider_db_mysql_util::append_name"); + DBUG_ENTER("spider_db_mbase_util::append_name"); str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); str->q_append(name, name_length); str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); DBUG_RETURN(0); } -int spider_db_mysql_util::append_name_with_charset( +int spider_db_mbase_util::append_name_with_charset( spider_string *str, const char *name, uint name_length, CHARSET_INFO *name_charset ) { - DBUG_ENTER("spider_db_mysql_util::append_name_with_charset"); + DBUG_ENTER("spider_db_mbase_util::append_name_with_charset"); if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN * 2 + name_length * 2)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); @@ -3207,17 +3396,17 @@ int spider_db_mysql_util::append_name_with_charset( DBUG_RETURN(0); } -bool spider_db_mysql_util::is_name_quote( +bool spider_db_mbase_util::is_name_quote( const char head_code ) { - DBUG_ENTER("spider_db_mysql_util::is_name_quote"); + DBUG_ENTER("spider_db_mbase_util::is_name_quote"); DBUG_RETURN(head_code == *name_quote_str); } -int spider_db_mysql_util::append_escaped_name_quote( +int spider_db_mbase_util::append_escaped_name_quote( spider_string *str ) { - DBUG_ENTER("spider_db_mysql_util::append_escaped_name_quote"); + DBUG_ENTER("spider_db_mbase_util::append_escaped_name_quote"); if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN * 2)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); @@ -3225,7 +3414,7 @@ int spider_db_mysql_util::append_escaped_name_quote( DBUG_RETURN(0); } -int spider_db_mysql_util::append_column_value( +int spider_db_mbase_util::append_column_value( ha_spider *spider, spider_string *str, Field *field, @@ -3238,7 +3427,7 @@ int spider_db_mysql_util::append_column_value( uint length; THD *thd = field->table->in_use; Time_zone *saved_time_zone = thd->variables.time_zone; - DBUG_ENTER("spider_db_mysql_util::append_column_value"); + DBUG_ENTER("spider_db_mbase_util::append_column_value"); tmp_str.init_calc_mem(113); thd->variables.time_zone = UTC; @@ -3403,7 +3592,7 @@ int spider_db_mysql_util::append_column_value( DBUG_RETURN(0); } -int spider_db_mysql_util::append_from_with_alias( +int spider_db_mbase_util::append_from_with_alias( spider_string *str, const char **table_names, uint *table_name_lengths, @@ -3414,7 +3603,7 @@ int spider_db_mysql_util::append_from_with_alias( bool over_write ) { uint roop_count, length = 0; - DBUG_ENTER("spider_db_mysql_util::append_from_with_alias"); + DBUG_ENTER("spider_db_mbase_util::append_from_with_alias"); DBUG_PRINT("info",("spider this=%p", this)); if (!over_write) { @@ -3437,11 +3626,11 @@ int spider_db_mysql_util::append_from_with_alias( DBUG_RETURN(0); } -int spider_db_mysql_util::append_trx_isolation( +int spider_db_mbase_util::append_trx_isolation( spider_string *str, int trx_isolation ) { - DBUG_ENTER("spider_db_mysql_util::append_trx_isolation"); + DBUG_ENTER("spider_db_mbase_util::append_trx_isolation"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SEMICOLON_LEN + SPIDER_SQL_ISO_READ_UNCOMMITTED_LEN)) @@ -3474,11 +3663,11 @@ int spider_db_mysql_util::append_trx_isolation( DBUG_RETURN(0); } -int spider_db_mysql_util::append_autocommit( +int spider_db_mbase_util::append_autocommit( spider_string *str, bool autocommit ) { - DBUG_ENTER("spider_db_mysql_util::append_autocommit"); + DBUG_ENTER("spider_db_mbase_util::append_autocommit"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SEMICOLON_LEN + SPIDER_SQL_AUTOCOMMIT_OFF_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -3497,11 +3686,11 @@ int spider_db_mysql_util::append_autocommit( DBUG_RETURN(0); } -int spider_db_mysql_util::append_sql_log_off( +int spider_db_mbase_util::append_sql_log_off( spider_string *str, bool sql_log_off ) { - DBUG_ENTER("spider_db_mysql_util::append_sql_log_off"); + DBUG_ENTER("spider_db_mbase_util::append_sql_log_off"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SEMICOLON_LEN + SPIDER_SQL_SQL_LOG_OFF_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -3518,12 +3707,12 @@ int spider_db_mysql_util::append_sql_log_off( DBUG_RETURN(0); } -int spider_db_mysql_util::append_time_zone( +int spider_db_mbase_util::append_time_zone( spider_string *str, Time_zone *time_zone ) { const String *tz_str = time_zone->get_name(); - DBUG_ENTER("spider_db_mysql_util::append_time_zone"); + DBUG_ENTER("spider_db_mbase_util::append_time_zone"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SEMICOLON_LEN + SPIDER_SQL_TIME_ZONE_LEN + tz_str->length() + SPIDER_SQL_VALUE_QUOTE_LEN)) @@ -3536,10 +3725,10 @@ int spider_db_mysql_util::append_time_zone( DBUG_RETURN(0); } -int spider_db_mysql_util::append_start_transaction( +int spider_db_mbase_util::append_start_transaction( spider_string *str ) { - DBUG_ENTER("spider_db_mysql_util::append_start_transaction"); + DBUG_ENTER("spider_db_mbase_util::append_start_transaction"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SEMICOLON_LEN + SPIDER_SQL_START_TRANSACTION_LEN)) @@ -3553,11 +3742,11 @@ int spider_db_mysql_util::append_start_transaction( DBUG_RETURN(0); } -int spider_db_mysql_util::append_xa_start( +int spider_db_mbase_util::append_xa_start( spider_string *str, XID *xid ) { - DBUG_ENTER("spider_db_mysql_util::append_xa_start"); + DBUG_ENTER("spider_db_mbase_util::append_xa_start"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SEMICOLON_LEN + SPIDER_SQL_XA_START_LEN + XIDDATASIZE + sizeof(long) + 9)) @@ -3571,10 +3760,10 @@ int spider_db_mysql_util::append_xa_start( DBUG_RETURN(0); } -int spider_db_mysql_util::append_lock_table_head( +int spider_db_mbase_util::append_lock_table_head( spider_string *str ) { - DBUG_ENTER("spider_db_mysql_util::append_lock_table_head"); + DBUG_ENTER("spider_db_mbase_util::append_lock_table_head"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_LOCK_TABLE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -3582,7 +3771,7 @@ int spider_db_mysql_util::append_lock_table_head( DBUG_RETURN(0); } -int spider_db_mysql_util::append_lock_table_body( +int spider_db_mbase_util::append_lock_table_body( spider_string *str, const char *db_name, uint db_name_length, @@ -3592,7 +3781,7 @@ int spider_db_mysql_util::append_lock_table_body( CHARSET_INFO *table_name_charset, int lock_type ) { - DBUG_ENTER("spider_db_mysql_util::append_lock_table_body"); + DBUG_ENTER("spider_db_mbase_util::append_lock_table_body"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN)) { @@ -3621,19 +3810,19 @@ int spider_db_mysql_util::append_lock_table_body( DBUG_RETURN(0); } -int spider_db_mysql_util::append_lock_table_tail( +int spider_db_mbase_util::append_lock_table_tail( spider_string *str ) { - DBUG_ENTER("spider_db_mysql_util::append_lock_table_tail"); + DBUG_ENTER("spider_db_mbase_util::append_lock_table_tail"); DBUG_PRINT("info",("spider this=%p", this)); str->length(str->length() - SPIDER_SQL_COMMA_LEN); DBUG_RETURN(0); } -int spider_db_mysql_util::append_unlock_table( +int spider_db_mbase_util::append_unlock_table( spider_string *str ) { - DBUG_ENTER("spider_db_mysql_util::append_unlock_table"); + DBUG_ENTER("spider_db_mbase_util::append_unlock_table"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_UNLOCK_TABLE_LEN)) { @@ -3643,7 +3832,7 @@ int spider_db_mysql_util::append_unlock_table( DBUG_RETURN(0); } -int spider_db_mysql_util::open_item_func( +int spider_db_mbase_util::open_item_func( Item_func *item_func, ha_spider *spider, spider_string *str, @@ -3652,7 +3841,6 @@ int spider_db_mysql_util::open_item_func( bool use_fields, spider_fields *fields ) { - uint dbton_id = spider_dbton_mysql.dbton_id; int error_num; Item *item, **item_list = item_func->arguments(); Field *field; @@ -3665,7 +3853,7 @@ int spider_db_mysql_util::open_item_func( last_str_length = SPIDER_SQL_NULL_CHAR_LEN; int use_pushdown_udf; bool merge_func = FALSE; - DBUG_ENTER("spider_db_mysql_util::open_item_func"); + DBUG_ENTER("spider_db_mbase_util::open_item_func"); if (str) { if (str->reserve(SPIDER_SQL_OPEN_PAREN_LEN)) @@ -4730,7 +4918,7 @@ int spider_db_mysql_util::open_item_func( } #ifdef HANDLER_HAS_DIRECT_AGGREGATE -int spider_db_mysql_util::open_item_sum_func( +int spider_db_mbase_util::open_item_sum_func( Item_sum *item_sum, ha_spider *spider, spider_string *str, @@ -4739,10 +4927,9 @@ int spider_db_mysql_util::open_item_sum_func( bool use_fields, spider_fields *fields ) { - uint dbton_id = spider_dbton_mysql.dbton_id; uint roop_count, item_count = item_sum->get_arg_count(); int error_num; - DBUG_ENTER("spider_db_mysql_util::open_item_sum_func"); + DBUG_ENTER("spider_db_mbase_util::open_item_sum_func"); DBUG_PRINT("info",("spider Sumfunctype = %d", item_sum->sum_func())); switch (item_sum->sum_func()) { @@ -4848,11 +5035,11 @@ int spider_db_mysql_util::open_item_sum_func( } #endif -int spider_db_mysql_util::append_escaped_util( +int spider_db_mbase_util::append_escaped_util( spider_string *to, String *from ) { - DBUG_ENTER("spider_db_mysql_util::append_escaped_util"); + DBUG_ENTER("spider_db_mbase_util::append_escaped_util"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider from=%s", from->charset()->csname)); DBUG_PRINT("info",("spider to=%s", to->charset()->csname)); @@ -4861,7 +5048,7 @@ int spider_db_mysql_util::append_escaped_util( } #ifdef SPIDER_HAS_GROUP_BY_HANDLER -int spider_db_mysql_util::append_table( +int spider_db_mbase_util::append_table( ha_spider *spider, spider_fields *fields, spider_string *str, @@ -4874,13 +5061,12 @@ int spider_db_mysql_util::append_table( ) { int error_num; bool use_cond_table_list = FALSE; - spider_mysql_share *db_share; - spider_mysql_handler *dbton_hdl; + spider_mbase_share *db_share; + spider_mbase_handler *dbton_hdl; SPIDER_TABLE_HOLDER *table_holder; - uint dbton_id = spider_dbton_mysql.dbton_id; TABLE_LIST *cond_table_list = *cond_table_list_ptr; ha_spider *spd; - DBUG_ENTER("spider_db_mysql_util::append_table"); + DBUG_ENTER("spider_db_mbase_util::append_table"); DBUG_PRINT("info",("spider table_list=%p", table_list)); DBUG_PRINT("info",("spider table_list->outer_join=%u", table_list->outer_join)); @@ -4987,9 +5173,9 @@ int spider_db_mysql_util::append_table( { table_holder = fields->get_table_holder(table_list->table); spd = table_holder->spider; - db_share = (spider_mysql_share *) + db_share = (spider_mbase_share *) spd->share->dbton_share[dbton_id]; - dbton_hdl = (spider_mysql_handler *) + dbton_hdl = (spider_mbase_handler *) spd->dbton_handler[dbton_id]; dbton_hdl->table_name_pos = str->length(); @@ -5084,7 +5270,7 @@ int spider_db_mysql_util::append_table( DBUG_RETURN(0); } -int spider_db_mysql_util::append_tables_top_down( +int spider_db_mbase_util::append_tables_top_down( ha_spider *spider, spider_fields *fields, spider_string *str, @@ -5097,7 +5283,7 @@ int spider_db_mysql_util::append_tables_top_down( uint outer_join_backup; TABLE_LIST *cur_table_list, *prev_table_list = NULL, *cond_table_list = NULL; bool first; - DBUG_ENTER("spider_db_mysql_util::append_tables_top_down"); + DBUG_ENTER("spider_db_mbase_util::append_tables_top_down"); DBUG_PRINT("info",("spider this=%p", this)); if ( table_list->outer_join || @@ -5223,7 +5409,7 @@ int spider_db_mysql_util::append_tables_top_down( str->q_append(SPIDER_SQL_ON_STR, SPIDER_SQL_ON_LEN); } if ((error_num = spider_db_print_item_type(on_expr, NULL, - spider, str, NULL, 0, spider_dbton_mysql.dbton_id, TRUE, fields))) + spider, str, NULL, 0, dbton_id, TRUE, fields))) { DBUG_RETURN(error_num); } @@ -5232,14 +5418,14 @@ int spider_db_mysql_util::append_tables_top_down( DBUG_RETURN(0); } -int spider_db_mysql_util::append_tables_top_down_check( +int spider_db_mbase_util::append_tables_top_down_check( TABLE_LIST *table_list, TABLE_LIST **used_table_list, uint *current_pos ) { int error_num; TABLE_LIST *cur_table_list; - DBUG_ENTER("spider_db_mysql_util::append_tables_top_down_check"); + DBUG_ENTER("spider_db_mbase_util::append_tables_top_down_check"); DBUG_PRINT("info",("spider this=%p", this)); List_iterator_fast it1(table_list->nested_join->join_list); while ((cur_table_list = it1++)) @@ -5256,7 +5442,7 @@ int spider_db_mysql_util::append_tables_top_down_check( DBUG_RETURN(0); } -int spider_db_mysql_util::append_embedding_tables( +int spider_db_mbase_util::append_embedding_tables( ha_spider *spider, spider_fields *fields, spider_string *str, @@ -5267,7 +5453,7 @@ int spider_db_mysql_util::append_embedding_tables( ) { int error_num; TABLE_LIST *embedding = table_list->embedding; - DBUG_ENTER("spider_db_mysql_util::append_embedding_tables"); + DBUG_ENTER("spider_db_mbase_util::append_embedding_tables"); DBUG_PRINT("info",("spider this=%p", this)); if (embedding) { @@ -5310,7 +5496,7 @@ int spider_db_mysql_util::append_embedding_tables( DBUG_RETURN(0); } -int spider_db_mysql_util::append_from_and_tables( +int spider_db_mbase_util::append_from_and_tables( ha_spider *spider, spider_fields *fields, spider_string *str, @@ -5322,7 +5508,7 @@ int spider_db_mysql_util::append_from_and_tables( TABLE *table; TABLE_LIST **used_table_list, *prev_table_list = NULL, *cond_table_list = NULL; - DBUG_ENTER("spider_db_mysql_util::append_from_and_tables"); + DBUG_ENTER("spider_db_mbase_util::append_from_and_tables"); DBUG_PRINT("info",("spider this=%p", this)); used_table_list = (TABLE_LIST **) my_alloca(sizeof(TABLE_LIST *) * table_count); @@ -5387,19 +5573,19 @@ int spider_db_mysql_util::append_from_and_tables( DBUG_RETURN(0); } -int spider_db_mysql_util::reappend_tables( +int spider_db_mbase_util::reappend_tables( spider_fields *fields, SPIDER_LINK_IDX_CHAIN *link_idx_chain, spider_string *str ) { int error_num; - uint dbton_id = spider_dbton_mysql.dbton_id, length; + uint32 length; ha_spider *spider; - spider_mysql_share *db_share; - spider_mysql_handler *dbton_hdl; + spider_mbase_share *db_share; + spider_mbase_handler *dbton_hdl; SPIDER_TABLE_HOLDER *table_holder; SPIDER_LINK_IDX_HOLDER *link_idx_holder; - DBUG_ENTER("spider_db_mysql_util::reappend_tables"); + DBUG_ENTER("spider_db_mbase_util::reappend_tables"); DBUG_PRINT("info",("spider this=%p", this)); length = str->length(); fields->set_pos_to_first_table_on_link_idx_chain(link_idx_chain); @@ -5409,11 +5595,11 @@ int spider_db_mysql_util::reappend_tables( link_idx_holder = fields->get_next_table_on_link_idx_chain(link_idx_chain); spider = table_holder->spider; - db_share = (spider_mysql_share *) + db_share = (spider_mbase_share *) spider->share->dbton_share[dbton_id]; if (!db_share->same_db_table_name) { - dbton_hdl = (spider_mysql_handler *) spider->dbton_handler[dbton_id]; + dbton_hdl = (spider_mbase_handler *) spider->dbton_handler[dbton_id]; str->length(dbton_hdl->table_name_pos); if ((error_num = db_share->append_table_name_with_adjusting(str, spider->conn_link_idx[link_idx_holder->link_idx]))) @@ -5426,10 +5612,10 @@ int spider_db_mysql_util::reappend_tables( DBUG_RETURN(0); } -int spider_db_mysql_util::append_where( +int spider_db_mbase_util::append_where( spider_string *str ) { - DBUG_ENTER("spider_db_mysql_util::append_where"); + DBUG_ENTER("spider_db_mbase_util::append_where"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_WHERE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -5437,10 +5623,10 @@ int spider_db_mysql_util::append_where( DBUG_RETURN(0); } -int spider_db_mysql_util::append_having( +int spider_db_mbase_util::append_having( spider_string *str ) { - DBUG_ENTER("spider_db_mysql_util::append_having"); + DBUG_ENTER("spider_db_mbase_util::append_having"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_HAVING_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -5449,11 +5635,15 @@ int spider_db_mysql_util::append_having( } #endif -spider_mysql_share::spider_mysql_share( - st_spider_share *share +spider_mbase_share::spider_mbase_share( + st_spider_share *share, + uint dbton_id, + spider_db_mbase_util *spider_db_mbase_utility ) : spider_db_share( - share + share, + dbton_id ), + spider_db_mbase_utility(spider_db_mbase_utility), table_select(NULL), table_select_pos(0), key_select(NULL), @@ -5474,16 +5664,39 @@ spider_mysql_share::spider_mysql_share( same_db_table_name(TRUE), first_all_link_idx(-1) { - DBUG_ENTER("spider_mysql_share::spider_mysql_share"); + DBUG_ENTER("spider_mbase_share::spider_mbase_share"); DBUG_PRINT("info",("spider this=%p", this)); spider_alloc_calc_mem_init(mem_calc, 71); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); DBUG_VOID_RETURN; } -spider_mysql_share::~spider_mysql_share() +spider_mysql_share::spider_mysql_share( + st_spider_share *share +) : spider_mbase_share( + share, + spider_db_mysql_utility.dbton_id, + &spider_db_mysql_utility +) { + DBUG_ENTER("spider_mysql_share::spider_mysql_share"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} +spider_mariadb_share::spider_mariadb_share( + st_spider_share *share +) : spider_mbase_share( + share, + spider_db_mariadb_utility.dbton_id, + &spider_db_mariadb_utility +) { + DBUG_ENTER("spider_mariadb_share::spider_mariadb_share"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_mbase_share::~spider_mbase_share() { - DBUG_ENTER("spider_mysql_share::~spider_mysql_share"); + DBUG_ENTER("spider_mbase_share::~spider_mbase_share"); DBUG_PRINT("info",("spider this=%p", this)); if (table_select) delete [] table_select; @@ -5504,13 +5717,27 @@ spider_mysql_share::~spider_mysql_share() DBUG_VOID_RETURN; } -int spider_mysql_share::init() +spider_mysql_share::~spider_mysql_share() +{ + DBUG_ENTER("spider_mysql_share::~spider_mysql_share"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_mariadb_share::~spider_mariadb_share() +{ + DBUG_ENTER("spider_mariadb_share::~spider_mariadb_share"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +int spider_mbase_share::init() { int error_num; uint roop_count; TABLE_SHARE *table_share = spider_share->table_share; uint keys = table_share ? table_share->keys : 0; - DBUG_ENTER("spider_mysql_share::init"); + DBUG_ENTER("spider_mbase_share::init"); DBUG_PRINT("info",("spider this=%p", this)); if (!(key_select_pos = (int *) spider_bulk_alloc_mem(spider_current_trx, 112, @@ -5571,33 +5798,33 @@ int spider_mysql_share::init() DBUG_RETURN(error_num); } -uint spider_mysql_share::get_column_name_length( +uint spider_mbase_share::get_column_name_length( uint field_index ) { - DBUG_ENTER("spider_mysql_share::get_column_name_length"); + DBUG_ENTER("spider_mbase_share::get_column_name_length"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(column_name_str[field_index].length()); } -int spider_mysql_share::append_column_name( +int spider_mbase_share::append_column_name( spider_string *str, uint field_index ) { int error_num; - DBUG_ENTER("spider_mysql_share::append_column_name"); + DBUG_ENTER("spider_mbase_share::append_column_name"); DBUG_PRINT("info",("spider this=%p", this)); - error_num = spider_db_mysql_utility.append_name(str, + error_num = spider_db_mbase_utility->append_name(str, column_name_str[field_index].ptr(), column_name_str[field_index].length()); DBUG_RETURN(error_num); } -int spider_mysql_share::append_column_name_with_alias( +int spider_mbase_share::append_column_name_with_alias( spider_string *str, uint field_index, const char *alias, uint alias_length ) { - DBUG_ENTER("spider_mysql_share::append_column_name_with_alias"); + DBUG_ENTER("spider_mbase_share::append_column_name_with_alias"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve( alias_length + @@ -5609,7 +5836,7 @@ int spider_mysql_share::append_column_name_with_alias( DBUG_RETURN(0); } -int spider_mysql_share::append_table_name( +int spider_mbase_share::append_table_name( spider_string *str, int all_link_idx ) { @@ -5617,20 +5844,20 @@ int spider_mysql_share::append_table_name( uint db_nm_len = db_names_str[all_link_idx].length(); const char *table_nm = table_names_str[all_link_idx].ptr(); uint table_nm_len = table_names_str[all_link_idx].length(); - DBUG_ENTER("spider_mysql_share::append_table_name"); + DBUG_ENTER("spider_mbase_share::append_table_name"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(db_nm_len + SPIDER_SQL_DOT_LEN + table_nm_len + /* SPIDER_SQL_NAME_QUOTE_LEN */ 4)) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); } - spider_db_mysql_utility.append_name(str, db_nm, db_nm_len); + spider_db_mbase_utility->append_name(str, db_nm, db_nm_len); str->q_append(SPIDER_SQL_DOT_STR, SPIDER_SQL_DOT_LEN); - spider_db_mysql_utility.append_name(str, table_nm, table_nm_len); + spider_db_mbase_utility->append_name(str, table_nm, table_nm_len); DBUG_RETURN(0); } -int spider_mysql_share::append_table_name_with_adjusting( +int spider_mbase_share::append_table_name_with_adjusting( spider_string *str, int all_link_idx ) { @@ -5640,11 +5867,11 @@ int spider_mysql_share::append_table_name_with_adjusting( const char *table_nm = table_names_str[all_link_idx].ptr(); uint table_nm_len = table_names_str[all_link_idx].length(); uint table_nm_max_len = table_nm_max_length; - DBUG_ENTER("spider_mysql_share::append_table_name_with_adjusting"); + DBUG_ENTER("spider_mbase_share::append_table_name_with_adjusting"); DBUG_PRINT("info",("spider this=%p", this)); - spider_db_mysql_utility.append_name(str, db_nm, db_nm_len); + spider_db_mbase_utility->append_name(str, db_nm, db_nm_len); str->q_append(SPIDER_SQL_DOT_STR, SPIDER_SQL_DOT_LEN); - spider_db_mysql_utility.append_name(str, table_nm, table_nm_len); + spider_db_mbase_utility->append_name(str, table_nm, table_nm_len); uint length = db_nm_max_len - db_nm_len + table_nm_max_len - table_nm_len; @@ -5653,7 +5880,7 @@ int spider_mysql_share::append_table_name_with_adjusting( DBUG_RETURN(0); } -int spider_mysql_share::append_from_with_adjusted_table_name( +int spider_mbase_share::append_from_with_adjusted_table_name( spider_string *str, int *table_name_pos ) { @@ -5663,7 +5890,7 @@ int spider_mysql_share::append_from_with_adjusted_table_name( const char *table_nm = table_names_str[0].ptr(); uint table_nm_len = table_names_str[0].length(); uint table_nm_max_len = table_nm_max_length; - DBUG_ENTER("spider_mysql_share::append_from_with_adjusted_table_name"); + DBUG_ENTER("spider_mbase_share::append_from_with_adjusted_table_name"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_FROM_LEN + db_nm_max_length + SPIDER_SQL_DOT_LEN + table_nm_max_length + @@ -5673,9 +5900,9 @@ int spider_mysql_share::append_from_with_adjusted_table_name( } str->q_append(SPIDER_SQL_FROM_STR, SPIDER_SQL_FROM_LEN); *table_name_pos = str->length(); - spider_db_mysql_utility.append_name(str, db_nm, db_nm_len); + spider_db_mbase_utility->append_name(str, db_nm, db_nm_len); str->q_append(SPIDER_SQL_DOT_STR, SPIDER_SQL_DOT_LEN); - spider_db_mysql_utility.append_name(str, table_nm, table_nm_len); + spider_db_mbase_utility->append_name(str, table_nm, table_nm_len); uint length = db_nm_max_len - db_nm_len + table_nm_max_len - table_nm_len; @@ -5684,14 +5911,13 @@ int spider_mysql_share::append_from_with_adjusted_table_name( DBUG_RETURN(0); } -int spider_mysql_share::create_table_names_str() +int spider_mbase_share::create_table_names_str() { int error_num, roop_count; uint table_nm_len, db_nm_len; spider_string *str, *first_tbl_nm_str, *first_db_nm_str, *first_db_tbl_str; char *first_tbl_nm, *first_db_nm; - uint dbton_id = spider_dbton_mysql.dbton_id; - DBUG_ENTER("spider_mysql_share::create_table_names_str"); + DBUG_ENTER("spider_mbase_share::create_table_names_str"); table_names_str = NULL; db_names_str = NULL; db_table_str = NULL; @@ -5822,9 +6048,9 @@ error: DBUG_RETURN(error_num); } -void spider_mysql_share::free_table_names_str() +void spider_mbase_share::free_table_names_str() { - DBUG_ENTER("spider_mysql_share::free_table_names_str"); + DBUG_ENTER("spider_mbase_share::free_table_names_str"); if (db_table_str) { delete [] db_table_str; @@ -5843,14 +6069,13 @@ void spider_mysql_share::free_table_names_str() DBUG_VOID_RETURN; } -int spider_mysql_share::create_column_name_str() +int spider_mbase_share::create_column_name_str() { spider_string *str; int error_num; Field **field; TABLE_SHARE *table_share = spider_share->table_share; - uint dbton_id = spider_dbton_mysql.dbton_id; - DBUG_ENTER("spider_mysql_share::create_column_name_str"); + DBUG_ENTER("spider_mbase_share::create_column_name_str"); if ( table_share->fields && !(column_name_str = new spider_string[table_share->fields]) @@ -5876,9 +6101,9 @@ error: DBUG_RETURN(error_num); } -void spider_mysql_share::free_column_name_str() +void spider_mbase_share::free_column_name_str() { - DBUG_ENTER("spider_mysql_share::free_column_name_str"); + DBUG_ENTER("spider_mbase_share::free_column_name_str"); if (column_name_str) { delete [] column_name_str; @@ -5887,12 +6112,12 @@ void spider_mysql_share::free_column_name_str() DBUG_VOID_RETURN; } -int spider_mysql_share::convert_key_hint_str() +int spider_mbase_share::convert_key_hint_str() { spider_string *tmp_key_hint; int roop_count; TABLE_SHARE *table_share = spider_share->table_share; - DBUG_ENTER("spider_mysql_share::convert_key_hint_str"); + DBUG_ENTER("spider_mbase_share::convert_key_hint_str"); if (spider_share->access_charset->cset != system_charset_info->cset) { /* need conversion */ @@ -5915,11 +6140,10 @@ int spider_mysql_share::convert_key_hint_str() DBUG_RETURN(0); } -int spider_mysql_share::append_show_table_status() +int spider_mbase_share::append_show_table_status() { int roop_count; spider_string *str; - uint dbton_id = spider_dbton_mysql.dbton_id; DBUG_ENTER("spider_mysql_append_show_table_status"); if (!(show_table_status = new spider_string[2 * spider_share->all_link_count])) @@ -5987,7 +6211,7 @@ error: DBUG_RETURN(HA_ERR_OUT_OF_MEM); } -void spider_mysql_share::free_show_table_status() +void spider_mbase_share::free_show_table_status() { DBUG_ENTER("spider_mysql_free_show_table_status"); if (show_table_status) @@ -5998,12 +6222,11 @@ void spider_mysql_share::free_show_table_status() DBUG_VOID_RETURN; } -int spider_mysql_share::append_show_records() +int spider_mbase_share::append_show_records() { int roop_count; spider_string *str; - uint dbton_id = spider_dbton_mysql.dbton_id; - DBUG_ENTER("spider_mysql_share::append_show_records"); + DBUG_ENTER("spider_mbase_share::append_show_records"); if (!(show_records = new spider_string[spider_share->all_link_count])) goto error; @@ -6038,9 +6261,9 @@ error: DBUG_RETURN(HA_ERR_OUT_OF_MEM); } -void spider_mysql_share::free_show_records() +void spider_mbase_share::free_show_records() { - DBUG_ENTER("spider_mysql_share::free_show_records"); + DBUG_ENTER("spider_mbase_share::free_show_records"); if (show_records) { delete [] show_records; @@ -6049,12 +6272,11 @@ void spider_mysql_share::free_show_records() DBUG_VOID_RETURN; } -int spider_mysql_share::append_show_index() +int spider_mbase_share::append_show_index() { int roop_count; spider_string *str; - uint dbton_id = spider_dbton_mysql.dbton_id; - DBUG_ENTER("spider_mysql_share::append_show_index"); + DBUG_ENTER("spider_mbase_share::append_show_index"); if (!(show_index = new spider_string[2 * spider_share->all_link_count])) goto error; @@ -6113,9 +6335,9 @@ error: DBUG_RETURN(HA_ERR_OUT_OF_MEM); } -void spider_mysql_share::free_show_index() +void spider_mbase_share::free_show_index() { - DBUG_ENTER("spider_mysql_share::free_show_index"); + DBUG_ENTER("spider_mbase_share::free_show_index"); if (show_index) { delete [] show_index; @@ -6124,13 +6346,13 @@ void spider_mysql_share::free_show_index() DBUG_VOID_RETURN; } -int spider_mysql_share::append_table_select() +int spider_mbase_share::append_table_select() { Field **field; uint field_length; spider_string *str = table_select; TABLE_SHARE *table_share = spider_share->table_share; - DBUG_ENTER("spider_mysql_share::append_table_select"); + DBUG_ENTER("spider_mbase_share::append_table_select"); if (!*table_share->field) DBUG_RETURN(0); @@ -6148,7 +6370,7 @@ int spider_mysql_share::append_table_select() DBUG_RETURN(append_from_with_adjusted_table_name(str, &table_select_pos)); } -int spider_mysql_share::append_key_select( +int spider_mbase_share::append_key_select( uint idx ) { KEY_PART_INFO *key_part; @@ -6158,7 +6380,7 @@ int spider_mysql_share::append_key_select( spider_string *str = &key_select[idx]; TABLE_SHARE *table_share = spider_share->table_share; const KEY *key_info = &table_share->key_info[idx]; - DBUG_ENTER("spider_mysql_share::append_key_select"); + DBUG_ENTER("spider_mbase_share::append_key_select"); if (!spider_user_defined_key_parts(key_info)) DBUG_RETURN(0); @@ -6178,14 +6400,14 @@ int spider_mysql_share::append_key_select( DBUG_RETURN(append_from_with_adjusted_table_name(str, &key_select_pos[idx])); } -bool spider_mysql_share::need_change_db_table_name() +bool spider_mbase_share::need_change_db_table_name() { - DBUG_ENTER("spider_mysql_share::need_change_db_table_name"); + DBUG_ENTER("spider_mbase_share::need_change_db_table_name"); DBUG_RETURN(!same_db_table_name); } #ifdef SPIDER_HAS_DISCOVER_TABLE_STRUCTURE -int spider_mysql_share::discover_table_structure( +int spider_mbase_share::discover_table_structure( SPIDER_TRX *trx, SPIDER_SHARE *spider_share, spider_string *str @@ -6193,9 +6415,8 @@ int spider_mysql_share::discover_table_structure( int roop_count, error_num = HA_ERR_WRONG_COMMAND; char sql_buf[MAX_FIELD_WIDTH]; spider_string sql_str(sql_buf, sizeof(sql_buf), system_charset_info); - uint dbton_id = spider_dbton_mysql.dbton_id; uint strlen = str->length(); - DBUG_ENTER("spider_mysql_share::discover_table_structure"); + DBUG_ENTER("spider_mbase_share::discover_table_structure"); DBUG_PRINT("info",("spider this=%p", this)); sql_str.init_calc_mem(228); for (roop_count = 0; roop_count < (int) spider_share->all_link_count; @@ -6454,13 +6675,15 @@ int spider_mysql_share::discover_table_structure( } #endif -spider_mysql_handler::spider_mysql_handler( +spider_mbase_handler::spider_mbase_handler( ha_spider *spider, - spider_mysql_share *db_share + spider_mbase_share *db_share, + spider_db_mbase_util *spider_db_mbase_utility ) : spider_db_handler( spider, db_share ), + spider_db_mbase_utility(spider_db_mbase_utility), where_pos(0), order_pos(0), limit_pos(0), @@ -6484,16 +6707,42 @@ spider_mysql_handler::spider_mysql_handler( mysql_share(db_share), link_for_hash(NULL) { - DBUG_ENTER("spider_mysql_handler::spider_mysql_handler"); + DBUG_ENTER("spider_mbase_handler::spider_mbase_handler"); DBUG_PRINT("info",("spider this=%p", this)); spider_alloc_calc_mem_init(mem_calc, 183); spider_alloc_calc_mem(spider_current_trx, mem_calc, sizeof(*this)); DBUG_VOID_RETURN; } -spider_mysql_handler::~spider_mysql_handler() +spider_mysql_handler::spider_mysql_handler( + ha_spider *spider, + spider_mbase_share *db_share +) : spider_mbase_handler( + spider, + db_share, + &spider_db_mysql_utility +) { + DBUG_ENTER("spider_mysql_handler::spider_mysql_handler"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_mariadb_handler::spider_mariadb_handler( + ha_spider *spider, + spider_mbase_share *db_share +) : spider_mbase_handler( + spider, + db_share, + &spider_db_mariadb_utility +) { + DBUG_ENTER("spider_mariadb_handler::spider_mariadb_handler"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_mbase_handler::~spider_mbase_handler() { - DBUG_ENTER("spider_mysql_handler::~spider_mysql_handler"); + DBUG_ENTER("spider_mbase_handler::~spider_mbase_handler"); DBUG_PRINT("info",("spider this=%p", this)); while (union_table_name_pos_first) { @@ -6509,7 +6758,21 @@ spider_mysql_handler::~spider_mysql_handler() DBUG_VOID_RETURN; } -int spider_mysql_handler::init() +spider_mysql_handler::~spider_mysql_handler() +{ + DBUG_ENTER("spider_mysql_handler::~spider_mysql_handler"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_mariadb_handler::~spider_mariadb_handler() +{ + DBUG_ENTER("spider_mariadb_handler::~spider_mariadb_handler"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +int spider_mbase_handler::init() { uint roop_count; THD *thd = spider->trx->thd; @@ -6517,7 +6780,7 @@ int spider_mysql_handler::init() int init_sql_alloc_size = spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size); TABLE *table = spider->get_table(); - DBUG_ENTER("spider_mysql_handler::init"); + DBUG_ENTER("spider_mbase_handler::init"); DBUG_PRINT("info",("spider this=%p", this)); sql.init_calc_mem(59); sql_part.init_calc_mem(60); @@ -6572,7 +6835,7 @@ int spider_mysql_handler::init() } -int spider_mysql_handler::append_index_hint( +int spider_mbase_handler::append_index_hint( spider_string *str, int link_idx, ulong sql_type @@ -6583,7 +6846,7 @@ int spider_mysql_handler::append_index_hint( Index_hint *hint; // THD *thd = current_thd; int error_num = 0; - DBUG_ENTER("spider_mysql_handler::append_index_hint"); + DBUG_ENTER("spider_mbase_handler::append_index_hint"); DBUG_PRINT("info",("spider this=%p", this)); while(index_hints && (hint = iter++)) @@ -6626,13 +6889,13 @@ int spider_mysql_handler::append_index_hint( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_table_name_with_adjusting( +int spider_mbase_handler::append_table_name_with_adjusting( spider_string *str, int link_idx, ulong sql_type ) { int error_num = 0; - DBUG_ENTER("spider_mysql_handler::append_table_name_with_adjusting"); + DBUG_ENTER("spider_mbase_handler::append_table_name_with_adjusting"); DBUG_PRINT("info",("spider this=%p", this)); if (sql_type == SPIDER_SQL_TYPE_HANDLER) { @@ -6644,7 +6907,7 @@ int spider_mysql_handler::append_table_name_with_adjusting( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_key_column_types( +int spider_mbase_handler::append_key_column_types( const key_range *start_key, spider_string *str ) { @@ -6658,7 +6921,7 @@ int spider_mysql_handler::append_key_column_types( Field *field; char tmp_buf[MAX_FIELD_WIDTH]; spider_string tmp_str(tmp_buf, sizeof(tmp_buf), system_charset_info); - DBUG_ENTER("spider_mysql_handler::append_key_column_types"); + DBUG_ENTER("spider_mbase_handler::append_key_column_types"); DBUG_PRINT("info",("spider this=%p", this)); tmp_str.init_calc_mem(115); @@ -6712,7 +6975,7 @@ int spider_mysql_handler::append_key_column_types( DBUG_RETURN(0); } -int spider_mysql_handler::append_key_join_columns_for_bka( +int spider_mbase_handler::append_key_join_columns_for_bka( const key_range *start_key, spider_string *str, const char **table_aliases, @@ -6727,7 +6990,7 @@ int spider_mysql_handler::append_key_join_columns_for_bka( Field *field; char tmp_buf[MAX_FIELD_WIDTH]; bool start_where = ((int) str->length() == where_pos); - DBUG_ENTER("spider_mysql_handler::append_key_join_columns_for_bka"); + DBUG_ENTER("spider_mbase_handler::append_key_join_columns_for_bka"); DBUG_PRINT("info",("spider this=%p", this)); start_key_part_map = start_key->keypart_map & full_key_part_map; DBUG_PRINT("info", ("spider spider_user_defined_key_parts=%u", @@ -6776,11 +7039,11 @@ int spider_mysql_handler::append_key_join_columns_for_bka( DBUG_RETURN(0); } -int spider_mysql_handler::append_tmp_table_and_sql_for_bka( +int spider_mbase_handler::append_tmp_table_and_sql_for_bka( const key_range *start_key ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_tmp_table_and_sql_for_bka"); + DBUG_ENTER("spider_mbase_handler::append_tmp_table_and_sql_for_bka"); DBUG_PRINT("info",("spider this=%p", this)); char tmp_table_name[MAX_FIELD_WIDTH * 2], tgt_table_name[MAX_FIELD_WIDTH * 2]; @@ -6838,7 +7101,7 @@ int spider_mysql_handler::append_tmp_table_and_sql_for_bka( if ( (error_num = append_select_columns_with_alias(&sql, SPIDER_SQL_B_DOT_STR, SPIDER_SQL_B_DOT_LEN)) || - (error_num = spider_db_mysql_utility.append_from_with_alias(&sql, + (error_num = spider_db_mbase_utility->append_from_with_alias(&sql, table_names, table_name_lengths, table_aliases, table_alias_lengths, 2, &table_name_pos, FALSE)) @@ -6878,9 +7141,9 @@ int spider_mysql_handler::append_tmp_table_and_sql_for_bka( DBUG_RETURN(0); } -int spider_mysql_handler::reuse_tmp_table_and_sql_for_bka() +int spider_mbase_handler::reuse_tmp_table_and_sql_for_bka() { - DBUG_ENTER("spider_mysql_handler::reuse_tmp_table_and_sql_for_bka"); + DBUG_ENTER("spider_mbase_handler::reuse_tmp_table_and_sql_for_bka"); DBUG_PRINT("info",("spider this=%p", this)); tmp_sql.length(tmp_sql_pos4); sql.length(limit_pos); @@ -6888,13 +7151,13 @@ int spider_mysql_handler::reuse_tmp_table_and_sql_for_bka() DBUG_RETURN(0); } -void spider_mysql_handler::create_tmp_bka_table_name( +void spider_mbase_handler::create_tmp_bka_table_name( char *tmp_table_name, int *tmp_table_name_length, int link_idx ) { uint adjust_length, length; - DBUG_ENTER("spider_mysql_handler::create_tmp_bka_table_name"); + DBUG_ENTER("spider_mbase_handler::create_tmp_bka_table_name"); if (spider_param_bka_table_name_type(current_thd, mysql_share->spider_share-> bka_table_name_types[spider->conn_link_idx[link_idx]]) == 1) @@ -6936,7 +7199,7 @@ void spider_mysql_handler::create_tmp_bka_table_name( DBUG_VOID_RETURN; } -int spider_mysql_handler::append_create_tmp_bka_table( +int spider_mbase_handler::append_create_tmp_bka_table( const key_range *start_key, spider_string *str, char *tmp_table_name, @@ -6951,7 +7214,7 @@ int spider_mysql_handler::append_create_tmp_bka_table( uint bka_engine_length = strlen(bka_engine), cset_length = strlen(table_charset->csname), coll_length = strlen(table_charset->name); - DBUG_ENTER("spider_mysql_handler::append_create_tmp_bka_table"); + DBUG_ENTER("spider_mbase_handler::append_create_tmp_bka_table"); if (str->reserve(SPIDER_SQL_CREATE_TMP_LEN + tmp_table_name_length + SPIDER_SQL_OPEN_PAREN_LEN + SPIDER_SQL_ID_LEN + SPIDER_SQL_ID_TYPE_LEN + SPIDER_SQL_COMMA_LEN)) @@ -6979,7 +7242,7 @@ int spider_mysql_handler::append_create_tmp_bka_table( DBUG_RETURN(0); } -int spider_mysql_handler::append_drop_tmp_bka_table( +int spider_mbase_handler::append_drop_tmp_bka_table( spider_string *str, char *tmp_table_name, int tmp_table_name_length, @@ -6987,7 +7250,7 @@ int spider_mysql_handler::append_drop_tmp_bka_table( int *drop_table_end_pos, bool with_semicolon ) { - DBUG_ENTER("spider_mysql_handler::append_drop_tmp_bka_table"); + DBUG_ENTER("spider_mbase_handler::append_drop_tmp_bka_table"); if (str->reserve(SPIDER_SQL_DROP_TMP_LEN + tmp_table_name_length + (with_semicolon ? SPIDER_SQL_SEMICOLON_LEN : 0))) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -7000,7 +7263,7 @@ int spider_mysql_handler::append_drop_tmp_bka_table( DBUG_RETURN(0); } -int spider_mysql_handler::append_insert_tmp_bka_table( +int spider_mbase_handler::append_insert_tmp_bka_table( const key_range *start_key, spider_string *str, char *tmp_table_name, @@ -7008,7 +7271,7 @@ int spider_mysql_handler::append_insert_tmp_bka_table( int *db_name_pos ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_insert_tmp_bka_table"); + DBUG_ENTER("spider_mbase_handler::append_insert_tmp_bka_table"); if (str->reserve(SPIDER_SQL_INSERT_LEN + SPIDER_SQL_INTO_LEN + tmp_table_name_length + SPIDER_SQL_OPEN_PAREN_LEN + SPIDER_SQL_ID_LEN + SPIDER_SQL_COMMA_LEN)) @@ -7031,11 +7294,11 @@ int spider_mysql_handler::append_insert_tmp_bka_table( DBUG_RETURN(0); } -int spider_mysql_handler::append_union_table_and_sql_for_bka( +int spider_mbase_handler::append_union_table_and_sql_for_bka( const key_range *start_key ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_union_table_and_sql_for_bka"); + DBUG_ENTER("spider_mbase_handler::append_union_table_and_sql_for_bka"); DBUG_PRINT("info",("spider this=%p", this)); char tgt_table_name[MAX_FIELD_WIDTH * 2]; spider_string tgt_table_name_str(tgt_table_name, MAX_FIELD_WIDTH * 2, @@ -7082,7 +7345,7 @@ int spider_mysql_handler::append_union_table_and_sql_for_bka( tmp_sql_pos1 = sql.length(); if ( - (error_num = spider_db_mysql_utility.append_from_with_alias(&tmp_sql, + (error_num = spider_db_mbase_utility->append_from_with_alias(&tmp_sql, table_names, table_name_lengths, table_aliases, table_alias_lengths, 2, &table_name_pos, FALSE)) @@ -7124,15 +7387,15 @@ int spider_mysql_handler::append_union_table_and_sql_for_bka( DBUG_RETURN(0); } -int spider_mysql_handler::reuse_union_table_and_sql_for_bka() +int spider_mbase_handler::reuse_union_table_and_sql_for_bka() { - DBUG_ENTER("spider_mysql_handler::reuse_union_table_and_sql_for_bka"); + DBUG_ENTER("spider_mbase_handler::reuse_union_table_and_sql_for_bka"); DBUG_PRINT("info",("spider this=%p", this)); sql.length(tmp_sql_pos1); DBUG_RETURN(0); } -int spider_mysql_handler::append_insert_for_recovery( +int spider_mbase_handler::append_insert_for_recovery( ulong sql_type, int link_idx ) { @@ -7142,7 +7405,7 @@ int spider_mysql_handler::append_insert_for_recovery( uint field_name_length = 0; bool add_value = FALSE; spider_string *insert_sql; - DBUG_ENTER("spider_mysql_handler::append_insert_for_recovery"); + DBUG_ENTER("spider_mbase_handler::append_insert_for_recovery"); DBUG_PRINT("info",("spider this=%p", this)); if (sql_type == SPIDER_SQL_TYPE_INSERT_SQL) { @@ -7190,7 +7453,7 @@ int spider_mysql_handler::append_insert_for_recovery( insert_sql->q_append(SPIDER_SQL_NULL_STR, SPIDER_SQL_NULL_LEN); } else { if ( - spider_db_mysql_utility. + spider_db_mbase_utility-> append_column_value(spider, insert_sql, *field, NULL, share->access_charset) || insert_sql->reserve(SPIDER_SQL_COMMA_LEN) @@ -7211,13 +7474,13 @@ int spider_mysql_handler::append_insert_for_recovery( DBUG_RETURN(0); } -int spider_mysql_handler::append_update( +int spider_mbase_handler::append_update( const TABLE *table, my_ptrdiff_t ptr_diff ) { int error_num; spider_string *str = &update_sql; - DBUG_ENTER("spider_mysql_handler::append_update"); + DBUG_ENTER("spider_mbase_handler::append_update"); DBUG_PRINT("info",("spider this=%p", this)); if (str->length() > 0) { @@ -7236,7 +7499,7 @@ int spider_mysql_handler::append_update( DBUG_RETURN(0); } -int spider_mysql_handler::append_update( +int spider_mbase_handler::append_update( const TABLE *table, my_ptrdiff_t ptr_diff, int link_idx @@ -7244,7 +7507,7 @@ int spider_mysql_handler::append_update( int error_num; SPIDER_SHARE *share = spider->share; spider_string *str = &spider->result_list.update_sqls[link_idx]; - DBUG_ENTER("spider_mysql_handler::append_update"); + DBUG_ENTER("spider_mbase_handler::append_update"); DBUG_PRINT("info",("spider this=%p", this)); if (str->length() > 0) { @@ -7277,13 +7540,13 @@ int spider_mysql_handler::append_update( DBUG_RETURN(0); } -int spider_mysql_handler::append_delete( +int spider_mbase_handler::append_delete( const TABLE *table, my_ptrdiff_t ptr_diff ) { int error_num; spider_string *str = &update_sql; - DBUG_ENTER("spider_mysql_handler::append_delete"); + DBUG_ENTER("spider_mbase_handler::append_delete"); DBUG_PRINT("info",("spider this=%p", this)); if (str->length() > 0) { @@ -7303,14 +7566,14 @@ int spider_mysql_handler::append_delete( DBUG_RETURN(0); } -int spider_mysql_handler::append_delete( +int spider_mbase_handler::append_delete( const TABLE *table, my_ptrdiff_t ptr_diff, int link_idx ) { int error_num; spider_string *str = &spider->result_list.update_sqls[link_idx]; - DBUG_ENTER("spider_mysql_handler::append_delete"); + DBUG_ENTER("spider_mbase_handler::append_delete"); DBUG_PRINT("info",("spider this=%p", this)); if (str->length() > 0) { @@ -7330,21 +7593,21 @@ int spider_mysql_handler::append_delete( DBUG_RETURN(0); } -int spider_mysql_handler::append_insert_part() +int spider_mbase_handler::append_insert_part() { int error_num; - DBUG_ENTER("spider_mysql_handler::append_insert_part"); + DBUG_ENTER("spider_mbase_handler::append_insert_part"); DBUG_PRINT("info",("spider this=%p", this)); error_num = append_insert(&insert_sql, 0); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_insert( +int spider_mbase_handler::append_insert( spider_string *str, int link_idx ) { SPIDER_SHARE *share = spider->share; - DBUG_ENTER("spider_mysql_handler::append_insert"); + DBUG_ENTER("spider_mbase_handler::append_insert"); if ( ( spider->write_can_replace || @@ -7408,20 +7671,20 @@ int spider_mysql_handler::append_insert( DBUG_RETURN(0); } -int spider_mysql_handler::append_update_part() +int spider_mbase_handler::append_update_part() { int error_num; - DBUG_ENTER("spider_mysql_handler::append_update_part"); + DBUG_ENTER("spider_mbase_handler::append_update_part"); DBUG_PRINT("info",("spider this=%p", this)); error_num = append_update(&update_sql, 0); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_update( +int spider_mbase_handler::append_update( spider_string *str, int link_idx ) { - DBUG_ENTER("spider_mysql_handler::append_update"); + DBUG_ENTER("spider_mbase_handler::append_update"); if (str->reserve(SPIDER_SQL_UPDATE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_UPDATE_STR, SPIDER_SQL_UPDATE_LEN); @@ -7448,19 +7711,19 @@ int spider_mysql_handler::append_update( DBUG_RETURN(0); } -int spider_mysql_handler::append_delete_part() +int spider_mbase_handler::append_delete_part() { int error_num; - DBUG_ENTER("spider_mysql_handler::append_delete_part"); + DBUG_ENTER("spider_mbase_handler::append_delete_part"); DBUG_PRINT("info",("spider this=%p", this)); error_num = append_delete(&update_sql); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_delete( +int spider_mbase_handler::append_delete( spider_string *str ) { - DBUG_ENTER("spider_mysql_handler::append_delete"); + DBUG_ENTER("spider_mbase_handler::append_delete"); if (str->reserve(SPIDER_SQL_DELETE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_DELETE_STR, SPIDER_SQL_DELETE_LEN); @@ -7489,22 +7752,22 @@ int spider_mysql_handler::append_delete( #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS -int spider_mysql_handler::append_increment_update_set_part() +int spider_mbase_handler::append_increment_update_set_part() { int error_num; - DBUG_ENTER("spider_mysql_handler::append_increment_update_set_part"); + DBUG_ENTER("spider_mbase_handler::append_increment_update_set_part"); DBUG_PRINT("info",("spider this=%p", this)); error_num = append_increment_update_set(&update_sql); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_increment_update_set( +int spider_mbase_handler::append_increment_update_set( spider_string *str ) { uint field_name_length; uint roop_count; Field *field; - DBUG_ENTER("spider_mysql_handler::append_increment_update_set"); + DBUG_ENTER("spider_mbase_handler::append_increment_update_set"); if (str->reserve(SPIDER_SQL_SET_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_SET_STR, SPIDER_SQL_SET_LEN); @@ -7548,24 +7811,24 @@ int spider_mysql_handler::append_increment_update_set( #endif #endif -int spider_mysql_handler::append_update_set_part() +int spider_mbase_handler::append_update_set_part() { int error_num; - DBUG_ENTER("spider_mysql_handler::append_update_set_part"); + DBUG_ENTER("spider_mbase_handler::append_update_set_part"); DBUG_PRINT("info",("spider this=%p", this)); error_num = append_update_set(&update_sql); where_pos = update_sql.length(); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_update_set( +int spider_mbase_handler::append_update_set( spider_string *str ) { uint field_name_length; SPIDER_SHARE *share = spider->share; TABLE *table = spider->get_table(); Field **fields; - DBUG_ENTER("spider_mysql_handler::append_update_set"); + DBUG_ENTER("spider_mbase_handler::append_update_set"); if (str->reserve(SPIDER_SQL_SET_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_SET_STR, SPIDER_SQL_SET_LEN); @@ -7595,7 +7858,7 @@ int spider_mysql_handler::append_update_set( table->read_set); #endif if ( - spider_db_mysql_utility. + spider_db_mbase_utility-> append_column_value(spider, str, *fields, NULL, share->access_charset) || str->reserve(SPIDER_SQL_COMMA_LEN) @@ -7617,17 +7880,17 @@ int spider_mysql_handler::append_update_set( } #ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS -int spider_mysql_handler::append_direct_update_set_part() +int spider_mbase_handler::append_direct_update_set_part() { int error_num; - DBUG_ENTER("spider_mysql_handler::append_direct_update_set_part"); + DBUG_ENTER("spider_mbase_handler::append_direct_update_set_part"); DBUG_PRINT("info",("spider this=%p", this)); error_num = append_direct_update_set(&update_sql); where_pos = update_sql.length(); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_direct_update_set( +int spider_mbase_handler::append_direct_update_set( spider_string *str ) { #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) @@ -7637,7 +7900,7 @@ int spider_mysql_handler::append_direct_update_set( TABLE *table = spider->get_table(); #endif #endif - DBUG_ENTER("spider_mysql_handler::append_direct_update_set"); + DBUG_ENTER("spider_mbase_handler::append_direct_update_set"); if ( spider->direct_update_kinds == SPIDER_SQL_KIND_SQL && spider->direct_update_fields @@ -7646,7 +7909,7 @@ int spider_mysql_handler::append_direct_update_set( DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_SET_STR, SPIDER_SQL_SET_LEN); DBUG_RETURN(spider_db_append_update_columns(spider, str, NULL, 0, - spider_dbton_mysql.dbton_id, FALSE, NULL)); + dbton_id, FALSE, NULL)); } if ( @@ -7687,7 +7950,7 @@ int spider_mysql_handler::append_direct_update_set( table->read_set); #endif if ( - spider_db_mysql_utility. + spider_db_mbase_utility-> append_column_value(spider, str, top_table_field, NULL, share->access_charset) || str->reserve(SPIDER_SQL_COMMA_LEN) @@ -7711,57 +7974,57 @@ int spider_mysql_handler::append_direct_update_set( DBUG_RETURN(0); } -int spider_mysql_handler::append_dup_update_pushdown_part( +int spider_mbase_handler::append_dup_update_pushdown_part( const char *alias, uint alias_length ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_dup_update_pushdown_part"); + DBUG_ENTER("spider_mbase_handler::append_dup_update_pushdown_part"); DBUG_PRINT("info",("spider this=%p", this)); dup_update_sql.length(0); error_num = append_update_columns(&dup_update_sql, alias, alias_length); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_update_columns_part( +int spider_mbase_handler::append_update_columns_part( const char *alias, uint alias_length ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_update_columns_part"); + DBUG_ENTER("spider_mbase_handler::append_update_columns_part"); DBUG_PRINT("info",("spider this=%p", this)); error_num = append_update_columns(&update_sql, alias, alias_length); DBUG_RETURN(error_num); } -int spider_mysql_handler::check_update_columns_part() +int spider_mbase_handler::check_update_columns_part() { int error_num; - DBUG_ENTER("spider_mysql_handler::check_update_columns_part"); + DBUG_ENTER("spider_mbase_handler::check_update_columns_part"); DBUG_PRINT("info",("spider this=%p", this)); error_num = append_update_columns(NULL, NULL, 0); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_update_columns( +int spider_mbase_handler::append_update_columns( spider_string *str, const char *alias, uint alias_length ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_update_columns"); + DBUG_ENTER("spider_mbase_handler::append_update_columns"); error_num = spider_db_append_update_columns(spider, str, - alias, alias_length, spider_dbton_mysql.dbton_id, FALSE, NULL); + alias, alias_length, dbton_id, FALSE, NULL); DBUG_RETURN(error_num); } #endif -int spider_mysql_handler::append_select_part( +int spider_mbase_handler::append_select_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_select_part"); + DBUG_ENTER("spider_mbase_handler::append_select_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -7778,12 +8041,12 @@ int spider_mysql_handler::append_select_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_select( +int spider_mbase_handler::append_select( spider_string *str, ulong sql_type ) { SPIDER_RESULT_LIST *result_list = &spider->result_list; - DBUG_ENTER("spider_mysql_handler::append_select"); + DBUG_ENTER("spider_mbase_handler::append_select"); if (sql_type == SPIDER_SQL_TYPE_HANDLER) { if (str->reserve(SPIDER_SQL_HANDLER_LEN)) @@ -7854,12 +8117,12 @@ int spider_mysql_handler::append_select( DBUG_RETURN(0); } -int spider_mysql_handler::append_table_select_part( +int spider_mbase_handler::append_table_select_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_table_select_part"); + DBUG_ENTER("spider_mbase_handler::append_table_select_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -7873,23 +8136,23 @@ int spider_mysql_handler::append_table_select_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_table_select( +int spider_mbase_handler::append_table_select( spider_string *str ) { - DBUG_ENTER("spider_mysql_handler::append_table_select"); + DBUG_ENTER("spider_mbase_handler::append_table_select"); table_name_pos = str->length() + mysql_share->table_select_pos; if (str->append(*(mysql_share->table_select))) DBUG_RETURN(HA_ERR_OUT_OF_MEM); DBUG_RETURN(0); } -int spider_mysql_handler::append_key_select_part( +int spider_mbase_handler::append_key_select_part( ulong sql_type, uint idx ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_key_select_part"); + DBUG_ENTER("spider_mbase_handler::append_key_select_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -7903,23 +8166,23 @@ int spider_mysql_handler::append_key_select_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_key_select( +int spider_mbase_handler::append_key_select( spider_string *str, uint idx ) { - DBUG_ENTER("spider_mysql_handler::append_key_select"); + DBUG_ENTER("spider_mbase_handler::append_key_select"); table_name_pos = str->length() + mysql_share->key_select_pos[idx]; if (str->append(mysql_share->key_select[idx])) DBUG_RETURN(HA_ERR_OUT_OF_MEM); DBUG_RETURN(0); } -int spider_mysql_handler::append_minimum_select_part( +int spider_mbase_handler::append_minimum_select_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_minimum_select_part"); + DBUG_ENTER("spider_mbase_handler::append_minimum_select_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -7933,7 +8196,7 @@ int spider_mysql_handler::append_minimum_select_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_minimum_select( +int spider_mbase_handler::append_minimum_select( spider_string *str, ulong sql_type ) { @@ -7941,7 +8204,7 @@ int spider_mysql_handler::append_minimum_select( Field **field; int field_length; bool appended = FALSE; - DBUG_ENTER("spider_mysql_handler::append_minimum_select"); + DBUG_ENTER("spider_mbase_handler::append_minimum_select"); minimum_select_bitmap_create(); for (field = table->field; *field; field++) { @@ -7970,7 +8233,7 @@ int spider_mysql_handler::append_minimum_select( DBUG_RETURN(append_from(str, sql_type, first_link_idx)); } -int spider_mysql_handler::append_table_select_with_alias( +int spider_mbase_handler::append_table_select_with_alias( spider_string *str, const char *alias, uint alias_length @@ -7978,7 +8241,7 @@ int spider_mysql_handler::append_table_select_with_alias( TABLE *table = spider->get_table(); Field **field; int field_length; - DBUG_ENTER("spider_mysql_handler::append_table_select_with_alias"); + DBUG_ENTER("spider_mbase_handler::append_table_select_with_alias"); for (field = table->field; *field; field++) { field_length = @@ -7994,7 +8257,7 @@ int spider_mysql_handler::append_table_select_with_alias( DBUG_RETURN(0); } -int spider_mysql_handler::append_key_select_with_alias( +int spider_mbase_handler::append_key_select_with_alias( spider_string *str, const KEY *key_info, const char *alias, @@ -8004,7 +8267,7 @@ int spider_mysql_handler::append_key_select_with_alias( Field *field; uint part_num; int field_length; - DBUG_ENTER("spider_mysql_handler::append_key_select_with_alias"); + DBUG_ENTER("spider_mbase_handler::append_key_select_with_alias"); for (key_part = key_info->key_part, part_num = 0; part_num < spider_user_defined_key_parts(key_info); key_part++, part_num++) { @@ -8021,7 +8284,7 @@ int spider_mysql_handler::append_key_select_with_alias( DBUG_RETURN(0); } -int spider_mysql_handler::append_minimum_select_with_alias( +int spider_mbase_handler::append_minimum_select_with_alias( spider_string *str, const char *alias, uint alias_length @@ -8030,7 +8293,7 @@ int spider_mysql_handler::append_minimum_select_with_alias( Field **field; int field_length; bool appended = FALSE; - DBUG_ENTER("spider_mysql_handler::append_minimum_select_with_alias"); + DBUG_ENTER("spider_mbase_handler::append_minimum_select_with_alias"); minimum_select_bitmap_create(); for (field = table->field; *field; field++) { @@ -8060,14 +8323,14 @@ int spider_mysql_handler::append_minimum_select_with_alias( DBUG_RETURN(0); } -int spider_mysql_handler::append_select_columns_with_alias( +int spider_mbase_handler::append_select_columns_with_alias( spider_string *str, const char *alias, uint alias_length ) { int error_num; SPIDER_RESULT_LIST *result_list = &spider->result_list; - DBUG_ENTER("spider_mysql_handler::append_select_columns_with_alias"); + DBUG_ENTER("spider_mbase_handler::append_select_columns_with_alias"); #ifdef HANDLER_HAS_DIRECT_AGGREGATE if ( result_list->direct_aggregate && @@ -8089,12 +8352,12 @@ int spider_mysql_handler::append_select_columns_with_alias( DBUG_RETURN(append_minimum_select_with_alias(str, alias, alias_length)); } -int spider_mysql_handler::append_hint_after_table_part( +int spider_mbase_handler::append_hint_after_table_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_hint_after_table_part"); + DBUG_ENTER("spider_mbase_handler::append_hint_after_table_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -8118,11 +8381,11 @@ int spider_mysql_handler::append_hint_after_table_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_hint_after_table( +int spider_mbase_handler::append_hint_after_table( spider_string *str ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_hint_after_table"); + DBUG_ENTER("spider_mbase_handler::append_hint_after_table"); DBUG_PRINT("info",("spider this=%p", this)); if ( mysql_share->key_hint && @@ -8133,10 +8396,10 @@ int spider_mysql_handler::append_hint_after_table( DBUG_RETURN(0); } -void spider_mysql_handler::set_where_pos( +void spider_mbase_handler::set_where_pos( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::set_where_pos"); + DBUG_ENTER("spider_mbase_handler::set_where_pos"); switch (sql_type) { case SPIDER_SQL_TYPE_SELECT_SQL: @@ -8158,10 +8421,10 @@ void spider_mysql_handler::set_where_pos( DBUG_VOID_RETURN; } -void spider_mysql_handler::set_where_to_pos( +void spider_mbase_handler::set_where_to_pos( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::set_where_to_pos"); + DBUG_ENTER("spider_mbase_handler::set_where_to_pos"); switch (sql_type) { case SPIDER_SQL_TYPE_SELECT_SQL: @@ -8183,23 +8446,23 @@ void spider_mysql_handler::set_where_to_pos( DBUG_VOID_RETURN; } -int spider_mysql_handler::check_item_type( +int spider_mbase_handler::check_item_type( Item *item ) { int error_num; - DBUG_ENTER("spider_mysql_handler::check_item_type"); + DBUG_ENTER("spider_mbase_handler::check_item_type"); DBUG_PRINT("info",("spider this=%p", this)); error_num = spider_db_print_item_type(item, NULL, spider, NULL, NULL, 0, - spider_dbton_mysql.dbton_id, FALSE, NULL); + dbton_id, FALSE, NULL); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_values_connector_part( +int spider_mbase_handler::append_values_connector_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_values_connector_part"); + DBUG_ENTER("spider_mbase_handler::append_values_connector_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -8216,10 +8479,10 @@ int spider_mysql_handler::append_values_connector_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_values_connector( +int spider_mbase_handler::append_values_connector( spider_string *str ) { - DBUG_ENTER("spider_mysql_handler::append_values_connector"); + DBUG_ENTER("spider_mbase_handler::append_values_connector"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_COMMA_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) @@ -8230,12 +8493,12 @@ int spider_mysql_handler::append_values_connector( DBUG_RETURN(0); } -int spider_mysql_handler::append_values_terminator_part( +int spider_mbase_handler::append_values_terminator_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_values_terminator_part"); + DBUG_ENTER("spider_mbase_handler::append_values_terminator_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -8252,22 +8515,22 @@ int spider_mysql_handler::append_values_terminator_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_values_terminator( +int spider_mbase_handler::append_values_terminator( spider_string *str ) { - DBUG_ENTER("spider_mysql_handler::append_values_terminator"); + DBUG_ENTER("spider_mbase_handler::append_values_terminator"); DBUG_PRINT("info",("spider this=%p", this)); str->length(str->length() - SPIDER_SQL_COMMA_LEN - SPIDER_SQL_OPEN_PAREN_LEN); DBUG_RETURN(0); } -int spider_mysql_handler::append_union_table_connector_part( +int spider_mbase_handler::append_union_table_connector_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_union_table_connector_part"); + DBUG_ENTER("spider_mbase_handler::append_union_table_connector_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -8284,10 +8547,10 @@ int spider_mysql_handler::append_union_table_connector_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_union_table_connector( +int spider_mbase_handler::append_union_table_connector( spider_string *str ) { - DBUG_ENTER("spider_mysql_handler::append_union_table_connector"); + DBUG_ENTER("spider_mbase_handler::append_union_table_connector"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve((SPIDER_SQL_SPACE_LEN * 2) + SPIDER_SQL_UNION_ALL_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -8297,12 +8560,12 @@ int spider_mysql_handler::append_union_table_connector( DBUG_RETURN(0); } -int spider_mysql_handler::append_union_table_terminator_part( +int spider_mbase_handler::append_union_table_terminator_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_union_table_terminator_part"); + DBUG_ENTER("spider_mbase_handler::append_union_table_terminator_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -8316,10 +8579,10 @@ int spider_mysql_handler::append_union_table_terminator_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_union_table_terminator( +int spider_mbase_handler::append_union_table_terminator( spider_string *str ) { - DBUG_ENTER("spider_mysql_handler::append_union_table_terminator"); + DBUG_ENTER("spider_mbase_handler::append_union_table_terminator"); DBUG_PRINT("info",("spider this=%p", this)); str->length(str->length() - ((SPIDER_SQL_SPACE_LEN * 2) + SPIDER_SQL_UNION_ALL_LEN)); @@ -8334,13 +8597,13 @@ int spider_mysql_handler::append_union_table_terminator( DBUG_RETURN(0); } -int spider_mysql_handler::append_key_column_values_part( +int spider_mbase_handler::append_key_column_values_part( const key_range *start_key, ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_key_column_values_part"); + DBUG_ENTER("spider_mbase_handler::append_key_column_values_part"); switch (sql_type) { case SPIDER_SQL_TYPE_SELECT_SQL: @@ -8356,7 +8619,7 @@ int spider_mysql_handler::append_key_column_values_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_key_column_values( +int spider_mbase_handler::append_key_column_values( spider_string *str, const key_range *start_key ) { @@ -8372,7 +8635,7 @@ int spider_mysql_handler::append_key_column_values( key_part_map start_key_part_map; KEY_PART_INFO *key_part; Field *field; - DBUG_ENTER("spider_mysql_handler::append_key_column_values"); + DBUG_ENTER("spider_mbase_handler::append_key_column_values"); start_key_part_map = start_key->keypart_map & full_key_part_map; DBUG_PRINT("info", ("spider spider_user_defined_key_parts=%u", spider_user_defined_key_parts(key_info))); @@ -8398,7 +8661,7 @@ int spider_mysql_handler::append_key_column_values( if (error_num > 0) DBUG_RETURN(error_num); } else { - if (spider_db_mysql_utility.append_column_value(spider, str, field, ptr, + if (spider_db_mbase_utility->append_column_value(spider, str, field, ptr, share->access_charset)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); } @@ -8411,13 +8674,13 @@ int spider_mysql_handler::append_key_column_values( DBUG_RETURN(0); } -int spider_mysql_handler::append_key_column_values_with_name_part( +int spider_mbase_handler::append_key_column_values_with_name_part( const key_range *start_key, ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_key_column_values_with_name_part"); + DBUG_ENTER("spider_mbase_handler::append_key_column_values_with_name_part"); switch (sql_type) { case SPIDER_SQL_TYPE_SELECT_SQL: @@ -8433,7 +8696,7 @@ int spider_mysql_handler::append_key_column_values_with_name_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_key_column_values_with_name( +int spider_mbase_handler::append_key_column_values_with_name( spider_string *str, const key_range *start_key ) { @@ -8451,7 +8714,7 @@ int spider_mysql_handler::append_key_column_values_with_name( KEY_PART_INFO *key_part; Field *field; char tmp_buf[MAX_FIELD_WIDTH]; - DBUG_ENTER("spider_mysql_handler::append_key_column_values_with_name"); + DBUG_ENTER("spider_mbase_handler::append_key_column_values_with_name"); start_key_part_map = start_key->keypart_map & full_key_part_map; DBUG_PRINT("info", ("spider spider_user_defined_key_parts=%u", spider_user_defined_key_parts(key_info))); @@ -8479,7 +8742,7 @@ int spider_mysql_handler::append_key_column_values_with_name( if (error_num > 0) DBUG_RETURN(error_num); } else { - if (spider_db_mysql_utility.append_column_value(spider, str, field, ptr, + if (spider_db_mbase_utility->append_column_value(spider, str, field, ptr, share->access_charset)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); } @@ -8496,7 +8759,7 @@ int spider_mysql_handler::append_key_column_values_with_name( DBUG_RETURN(0); } -int spider_mysql_handler::append_key_where_part( +int spider_mbase_handler::append_key_where_part( const key_range *start_key, const key_range *end_key, ulong sql_type @@ -8504,7 +8767,7 @@ int spider_mysql_handler::append_key_where_part( int error_num; spider_string *str, *str_part = NULL, *str_part2 = NULL; bool set_order; - DBUG_ENTER("spider_mysql_handler::append_key_where_part"); + DBUG_ENTER("spider_mbase_handler::append_key_where_part"); switch (sql_type) { case SPIDER_SQL_TYPE_SELECT_SQL: @@ -8539,7 +8802,7 @@ int spider_mysql_handler::append_key_where_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_key_where( +int spider_mbase_handler::append_key_where( spider_string *str, spider_string *str_part, spider_string *str_part2, @@ -8549,14 +8812,14 @@ int spider_mysql_handler::append_key_where( bool set_order ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_key_where"); + DBUG_ENTER("spider_mbase_handler::append_key_where"); error_num = spider_db_append_key_where_internal(str, str_part, str_part2, start_key, end_key, spider, set_order, sql_type, - spider_dbton_mysql.dbton_id); + dbton_id); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_is_null_part( +int spider_mbase_handler::append_is_null_part( ulong sql_type, KEY_PART_INFO *key_part, const key_range *key, @@ -8566,7 +8829,7 @@ int spider_mysql_handler::append_is_null_part( ) { int error_num; spider_string *str, *str_part = NULL, *str_part2 = NULL; - DBUG_ENTER("spider_mysql_handler::append_is_null_part"); + DBUG_ENTER("spider_mbase_handler::append_is_null_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -8593,7 +8856,7 @@ int spider_mysql_handler::append_is_null_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_is_null( +int spider_mbase_handler::append_is_null( ulong sql_type, spider_string *str, spider_string *str_part, @@ -8604,7 +8867,7 @@ int spider_mysql_handler::append_is_null( bool key_eq, bool tgt_final ) { - DBUG_ENTER("spider_mysql_handler::append_is_null"); + DBUG_ENTER("spider_mbase_handler::append_is_null"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider key_eq=%s", key_eq ? "TRUE" : "FALSE")); if (key_part->null_bit) @@ -8677,14 +8940,14 @@ int spider_mysql_handler::append_is_null( DBUG_RETURN(0); } -int spider_mysql_handler::append_where_terminator_part( +int spider_mbase_handler::append_where_terminator_part( ulong sql_type, bool set_order, int key_count ) { int error_num; spider_string *str, *str_part = NULL, *str_part2 = NULL; - DBUG_ENTER("spider_mysql_handler::append_where_terminator_part"); + DBUG_ENTER("spider_mbase_handler::append_where_terminator_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -8711,7 +8974,7 @@ int spider_mysql_handler::append_where_terminator_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_where_terminator( +int spider_mbase_handler::append_where_terminator( ulong sql_type, spider_string *str, spider_string *str_part, @@ -8720,7 +8983,7 @@ int spider_mysql_handler::append_where_terminator( int key_count ) { SPIDER_RESULT_LIST *result_list = &spider->result_list; - DBUG_ENTER("spider_mysql_handler::append_where_terminator"); + DBUG_ENTER("spider_mbase_handler::append_where_terminator"); DBUG_PRINT("info",("spider this=%p", this)); if (sql_type != SPIDER_SQL_TYPE_HANDLER) { @@ -8750,12 +9013,12 @@ int spider_mysql_handler::append_where_terminator( DBUG_RETURN(0); } -int spider_mysql_handler::append_match_where_part( +int spider_mbase_handler::append_match_where_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_match_where_part"); + DBUG_ENTER("spider_mbase_handler::append_match_where_part"); switch (sql_type) { case SPIDER_SQL_TYPE_SELECT_SQL: @@ -8769,13 +9032,13 @@ int spider_mysql_handler::append_match_where_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_match_where( +int spider_mbase_handler::append_match_where( spider_string *str ) { int error_num; bool first = TRUE; st_spider_ft_info *ft_info = spider->ft_first; - DBUG_ENTER("spider_mysql_handler::append_match_where"); + DBUG_ENTER("spider_mbase_handler::append_match_where"); if (spider->ft_current) { while (TRUE) @@ -8806,7 +9069,7 @@ int spider_mysql_handler::append_match_where( DBUG_RETURN(0); } -int spider_mysql_handler::append_update_where( +int spider_mbase_handler::append_update_where( spider_string *str, const TABLE *table, my_ptrdiff_t ptr_diff @@ -8816,7 +9079,7 @@ int spider_mysql_handler::append_update_where( THD *thd = spider->trx->thd; SPIDER_SHARE *share = spider->share; bool no_pk = (table->s->primary_key == MAX_KEY); - DBUG_ENTER("spider_mysql_handler::append_update_where"); + DBUG_ENTER("spider_mbase_handler::append_update_where"); DBUG_PRINT("info", ("spider table->s->primary_key=%s", table->s->primary_key != MAX_KEY ? "TRUE" : "FALSE")); uint str_len_bakup = str->length(); @@ -8853,7 +9116,7 @@ int spider_mysql_handler::append_update_where( str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); (*field)->move_field_offset(ptr_diff); if ( - spider_db_mysql_utility. + spider_db_mbase_utility-> append_column_value(spider, str, *field, NULL, share->access_charset) || str->reserve(SPIDER_SQL_AND_LEN) @@ -8893,7 +9156,7 @@ int spider_mysql_handler::append_update_where( str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); (*field)->move_field_offset(ptr_diff); if ( - spider_db_mysql_utility. + spider_db_mbase_utility-> append_column_value(spider, str, *field, NULL, share->access_charset) || str->reserve(SPIDER_SQL_AND_LEN) @@ -8917,7 +9180,7 @@ int spider_mysql_handler::append_update_where( DBUG_RETURN(0); } -int spider_mysql_handler::append_condition_part( +int spider_mbase_handler::append_condition_part( const char *alias, uint alias_length, ulong sql_type, @@ -8926,7 +9189,7 @@ int spider_mysql_handler::append_condition_part( int error_num; spider_string *str; bool start_where = FALSE; - DBUG_ENTER("spider_mysql_handler::append_condition_part"); + DBUG_ENTER("spider_mbase_handler::append_condition_part"); switch (sql_type) { case SPIDER_SQL_TYPE_SELECT_SQL: @@ -9000,7 +9263,7 @@ int spider_mysql_handler::append_condition_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_condition( +int spider_mbase_handler::append_condition( spider_string *str, const char *alias, uint alias_length, @@ -9009,7 +9272,7 @@ int spider_mysql_handler::append_condition( ) { int error_num, restart_pos = 0, start_where_pos; SPIDER_CONDITION *tmp_cond = spider->condition; - DBUG_ENTER("spider_mysql_handler::append_condition"); + DBUG_ENTER("spider_mbase_handler::append_condition"); if (str && start_where) { start_where_pos = str->length(); @@ -9041,7 +9304,7 @@ int spider_mysql_handler::append_condition( } if ((error_num = spider_db_print_item_type( (Item *) tmp_cond->cond, NULL, spider, str, alias, alias_length, - spider_dbton_mysql.dbton_id, FALSE, NULL))) + dbton_id, FALSE, NULL))) { if (str && error_num == ER_SPIDER_COND_SKIP_NUM) { @@ -9056,7 +9319,7 @@ int spider_mysql_handler::append_condition( DBUG_RETURN(0); } -int spider_mysql_handler::append_match_against_part( +int spider_mbase_handler::append_match_against_part( ulong sql_type, st_spider_ft_info *ft_info, const char *alias, @@ -9064,7 +9327,7 @@ int spider_mysql_handler::append_match_against_part( ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_match_against_part"); + DBUG_ENTER("spider_mbase_handler::append_match_against_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9078,7 +9341,7 @@ int spider_mysql_handler::append_match_against_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_match_against( +int spider_mbase_handler::append_match_against( spider_string *str, st_spider_ft_info *ft_info, const char *alias, @@ -9092,7 +9355,7 @@ int spider_mysql_handler::append_match_against( int key_count; KEY_PART_INFO *key_part; Field *field; - DBUG_ENTER("spider_mysql_handler::append_match_against"); + DBUG_ENTER("spider_mbase_handler::append_match_against"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_MATCH_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -9141,7 +9404,7 @@ int spider_mysql_handler::append_match_against( tmp_str.append(ft_init_key->ptr(), ft_init_key->length(), ft_init_key->charset()) || str->reserve(tmp_str.length() * 2) || - spider_db_mysql_utility.append_escaped_util(str, tmp_str.get_str()) + spider_db_mbase_utility->append_escaped_util(str, tmp_str.get_str()) ) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->mem_calc(); @@ -9164,14 +9427,14 @@ int spider_mysql_handler::append_match_against( DBUG_RETURN(0); } -int spider_mysql_handler::append_match_select_part( +int spider_mbase_handler::append_match_select_part( ulong sql_type, const char *alias, uint alias_length ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_match_select_part"); + DBUG_ENTER("spider_mbase_handler::append_match_select_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9185,13 +9448,13 @@ int spider_mysql_handler::append_match_select_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_match_select( +int spider_mbase_handler::append_match_select( spider_string *str, const char *alias, uint alias_length ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_match_select"); + DBUG_ENTER("spider_mbase_handler::append_match_select"); DBUG_PRINT("info",("spider this=%p", this)); if (spider->ft_current) { @@ -9213,14 +9476,14 @@ int spider_mysql_handler::append_match_select( } #ifdef HANDLER_HAS_DIRECT_AGGREGATE -int spider_mysql_handler::append_sum_select_part( +int spider_mbase_handler::append_sum_select_part( ulong sql_type, const char *alias, uint alias_length ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_sum_select_part"); + DBUG_ENTER("spider_mbase_handler::append_sum_select_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9234,21 +9497,21 @@ int spider_mysql_handler::append_sum_select_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_sum_select( +int spider_mbase_handler::append_sum_select( spider_string *str, const char *alias, uint alias_length ) { int error_num; st_select_lex *select_lex; - DBUG_ENTER("spider_mysql_handler::append_sum_select"); + DBUG_ENTER("spider_mbase_handler::append_sum_select"); DBUG_PRINT("info",("spider this=%p", this)); select_lex = spider_get_select_lex(spider); JOIN *join = select_lex->join; Item_sum **item_sum_ptr; for (item_sum_ptr = join->sum_funcs; *item_sum_ptr; ++item_sum_ptr) { - if ((error_num = spider_db_mysql_utility.open_item_sum_func(*item_sum_ptr, + if ((error_num = spider_db_mbase_utility->open_item_sum_func(*item_sum_ptr, spider, str, alias, alias_length, FALSE, NULL))) { DBUG_RETURN(error_num); @@ -9261,10 +9524,10 @@ int spider_mysql_handler::append_sum_select( } #endif -void spider_mysql_handler::set_order_pos( +void spider_mbase_handler::set_order_pos( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::set_order_pos"); + DBUG_ENTER("spider_mbase_handler::set_order_pos"); switch (sql_type) { case SPIDER_SQL_TYPE_SELECT_SQL: @@ -9287,10 +9550,10 @@ void spider_mysql_handler::set_order_pos( DBUG_VOID_RETURN; } -void spider_mysql_handler::set_order_to_pos( +void spider_mbase_handler::set_order_to_pos( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::set_order_to_pos"); + DBUG_ENTER("spider_mbase_handler::set_order_to_pos"); switch (sql_type) { case SPIDER_SQL_TYPE_SELECT_SQL: @@ -9314,14 +9577,14 @@ void spider_mysql_handler::set_order_to_pos( } #ifdef HANDLER_HAS_DIRECT_AGGREGATE -int spider_mysql_handler::append_group_by_part( +int spider_mbase_handler::append_group_by_part( const char *alias, uint alias_length, ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_group_by_part"); + DBUG_ENTER("spider_mbase_handler::append_group_by_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9345,14 +9608,14 @@ int spider_mysql_handler::append_group_by_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_group_by( +int spider_mbase_handler::append_group_by( spider_string *str, const char *alias, uint alias_length ) { int error_num; st_select_lex *select_lex; - DBUG_ENTER("spider_mysql_handler::append_group_by"); + DBUG_ENTER("spider_mbase_handler::append_group_by"); DBUG_PRINT("info",("spider this=%p", this)); select_lex = spider_get_select_lex(spider); ORDER *group = (ORDER *) select_lex->group_list.first; @@ -9364,7 +9627,7 @@ int spider_mysql_handler::append_group_by( for (; group; group = group->next) { if ((error_num = spider_db_print_item_type((*group->item), NULL, spider, - str, alias, alias_length, spider_dbton_mysql.dbton_id, FALSE, NULL))) + str, alias, alias_length, dbton_id, FALSE, NULL))) { DBUG_RETURN(error_num); } @@ -9378,14 +9641,14 @@ int spider_mysql_handler::append_group_by( } #endif -int spider_mysql_handler::append_key_order_for_merge_with_alias_part( +int spider_mbase_handler::append_key_order_for_merge_with_alias_part( const char *alias, uint alias_length, ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_key_order_for_merge_with_alias_part"); + DBUG_ENTER("spider_mbase_handler::append_key_order_for_merge_with_alias_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9410,7 +9673,7 @@ int spider_mysql_handler::append_key_order_for_merge_with_alias_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_key_order_for_merge_with_alias( +int spider_mbase_handler::append_key_order_for_merge_with_alias( spider_string *str, const char *alias, uint alias_length @@ -9420,7 +9683,7 @@ int spider_mysql_handler::append_key_order_for_merge_with_alias( int length; Field *field; uint key_name_length; - DBUG_ENTER("spider_mysql_handler::append_key_order_for_merge_with_alias"); + DBUG_ENTER("spider_mbase_handler::append_key_order_for_merge_with_alias"); DBUG_PRINT("info",("spider this=%p", this)); #ifdef HANDLER_HAS_DIRECT_AGGREGATE if (spider->result_list.direct_aggregate) @@ -9494,14 +9757,14 @@ int spider_mysql_handler::append_key_order_for_merge_with_alias( DBUG_RETURN(0); } -int spider_mysql_handler::append_key_order_for_direct_order_limit_with_alias_part( +int spider_mbase_handler::append_key_order_for_direct_order_limit_with_alias_part( const char *alias, uint alias_length, ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_key_order_for_direct_order_limit_with_alias_part"); + DBUG_ENTER("spider_mbase_handler::append_key_order_for_direct_order_limit_with_alias_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9526,7 +9789,7 @@ int spider_mysql_handler::append_key_order_for_direct_order_limit_with_alias_par DBUG_RETURN(error_num); } -int spider_mysql_handler::append_key_order_for_direct_order_limit_with_alias( +int spider_mbase_handler::append_key_order_for_direct_order_limit_with_alias( spider_string *str, const char *alias, uint alias_length @@ -9536,7 +9799,7 @@ int spider_mysql_handler::append_key_order_for_direct_order_limit_with_alias( st_select_lex *select_lex; longlong select_limit; longlong offset_limit; - DBUG_ENTER("spider_mysql_handler::append_key_order_for_direct_order_limit_with_alias"); + DBUG_ENTER("spider_mbase_handler::append_key_order_for_direct_order_limit_with_alias"); DBUG_PRINT("info",("spider this=%p", this)); #ifdef HANDLER_HAS_DIRECT_AGGREGATE if (spider->result_list.direct_aggregate) @@ -9557,7 +9820,7 @@ int spider_mysql_handler::append_key_order_for_direct_order_limit_with_alias( { if ((error_num = spider_db_print_item_type((*order->item), NULL, spider, str, alias, - alias_length, spider_dbton_mysql.dbton_id, FALSE, NULL))) + alias_length, dbton_id, FALSE, NULL))) { DBUG_PRINT("info",("spider error=%d", error_num)); DBUG_RETURN(error_num); @@ -9580,14 +9843,14 @@ int spider_mysql_handler::append_key_order_for_direct_order_limit_with_alias( DBUG_RETURN(0); } -int spider_mysql_handler::append_key_order_with_alias_part( +int spider_mbase_handler::append_key_order_with_alias_part( const char *alias, uint alias_length, ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_key_order_with_alias_part"); + DBUG_ENTER("spider_mbase_handler::append_key_order_with_alias_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9612,12 +9875,12 @@ int spider_mysql_handler::append_key_order_with_alias_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_key_order_for_handler( +int spider_mbase_handler::append_key_order_for_handler( spider_string *str, const char *alias, uint alias_length ) { - DBUG_ENTER("spider_mysql_handler::append_key_order_for_handler"); + DBUG_ENTER("spider_mbase_handler::append_key_order_for_handler"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider ha_next_pos=%d", ha_next_pos)); DBUG_PRINT("info",("spider ha_where_pos=%d", ha_where_pos)); @@ -9627,7 +9890,7 @@ int spider_mysql_handler::append_key_order_for_handler( DBUG_RETURN(0); } -int spider_mysql_handler::append_key_order_with_alias( +int spider_mbase_handler::append_key_order_with_alias( spider_string *str, const char *alias, uint alias_length @@ -9638,7 +9901,7 @@ int spider_mysql_handler::append_key_order_with_alias( KEY_PART_INFO *key_part; Field *field; uint key_name_length; - DBUG_ENTER("spider_mysql_handler::append_key_order_with_alias"); + DBUG_ENTER("spider_mbase_handler::append_key_order_with_alias"); DBUG_PRINT("info",("spider this=%p", this)); #ifdef HANDLER_HAS_DIRECT_AGGREGATE if (spider->result_list.direct_aggregate) @@ -9793,14 +10056,14 @@ int spider_mysql_handler::append_key_order_with_alias( DBUG_RETURN(0); } -int spider_mysql_handler::append_limit_part( +int spider_mbase_handler::append_limit_part( longlong offset, longlong limit, ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_limit_part"); + DBUG_ENTER("spider_mbase_handler::append_limit_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9830,14 +10093,14 @@ int spider_mysql_handler::append_limit_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::reappend_limit_part( +int spider_mbase_handler::reappend_limit_part( longlong offset, longlong limit, ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::reappend_limit_part"); + DBUG_ENTER("spider_mbase_handler::reappend_limit_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9867,14 +10130,14 @@ int spider_mysql_handler::reappend_limit_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_limit( +int spider_mbase_handler::append_limit( spider_string *str, longlong offset, longlong limit ) { char buf[SPIDER_LONGLONG_LEN + 1]; uint32 length; - DBUG_ENTER("spider_mysql_handler::append_limit"); + DBUG_ENTER("spider_mbase_handler::append_limit"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info", ("spider offset=%lld", offset)); DBUG_PRINT("info", ("spider limit=%lld", limit)); @@ -9898,12 +10161,12 @@ int spider_mysql_handler::append_limit( DBUG_RETURN(0); } -int spider_mysql_handler::append_select_lock_part( +int spider_mbase_handler::append_select_lock_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_select_lock_part"); + DBUG_ENTER("spider_mbase_handler::append_select_lock_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9917,11 +10180,11 @@ int spider_mysql_handler::append_select_lock_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_select_lock( +int spider_mbase_handler::append_select_lock( spider_string *str ) { int lock_mode = spider_conn_lock_mode(spider); - DBUG_ENTER("spider_mysql_handler::append_select_lock"); + DBUG_ENTER("spider_mbase_handler::append_select_lock"); DBUG_PRINT("info",("spider this=%p", this)); if (lock_mode == SPIDER_LOCK_MODE_EXCLUSIVE) { @@ -9937,12 +10200,12 @@ int spider_mysql_handler::append_select_lock( DBUG_RETURN(0); } -int spider_mysql_handler::append_union_all_start_part( +int spider_mbase_handler::append_union_all_start_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_union_all_start_part"); + DBUG_ENTER("spider_mbase_handler::append_union_all_start_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9956,10 +10219,10 @@ int spider_mysql_handler::append_union_all_start_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_union_all_start( +int spider_mbase_handler::append_union_all_start( spider_string *str ) { - DBUG_ENTER("spider_mysql_handler::append_union_all_start"); + DBUG_ENTER("spider_mbase_handler::append_union_all_start"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_OPEN_PAREN_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -9967,12 +10230,12 @@ int spider_mysql_handler::append_union_all_start( DBUG_RETURN(0); } -int spider_mysql_handler::append_union_all_part( +int spider_mbase_handler::append_union_all_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_union_all_part"); + DBUG_ENTER("spider_mbase_handler::append_union_all_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -9986,10 +10249,10 @@ int spider_mysql_handler::append_union_all_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_union_all( +int spider_mbase_handler::append_union_all( spider_string *str ) { - DBUG_ENTER("spider_mysql_handler::append_union_all"); + DBUG_ENTER("spider_mbase_handler::append_union_all"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_UNION_ALL_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -9997,12 +10260,12 @@ int spider_mysql_handler::append_union_all( DBUG_RETURN(0); } -int spider_mysql_handler::append_union_all_end_part( +int spider_mbase_handler::append_union_all_end_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_union_all_end_part"); + DBUG_ENTER("spider_mbase_handler::append_union_all_end_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10016,24 +10279,24 @@ int spider_mysql_handler::append_union_all_end_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_union_all_end( +int spider_mbase_handler::append_union_all_end( spider_string *str ) { - DBUG_ENTER("spider_mysql_handler::append_union_all_end"); + DBUG_ENTER("spider_mbase_handler::append_union_all_end"); DBUG_PRINT("info",("spider this=%p", this)); str->length(str->length() - SPIDER_SQL_UNION_ALL_LEN + SPIDER_SQL_CLOSE_PAREN_LEN); DBUG_RETURN(0); } -int spider_mysql_handler::append_multi_range_cnt_part( +int spider_mbase_handler::append_multi_range_cnt_part( ulong sql_type, uint multi_range_cnt, bool with_comma ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_multi_range_cnt_part"); + DBUG_ENTER("spider_mbase_handler::append_multi_range_cnt_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10050,14 +10313,14 @@ int spider_mysql_handler::append_multi_range_cnt_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_multi_range_cnt( +int spider_mbase_handler::append_multi_range_cnt( spider_string *str, uint multi_range_cnt, bool with_comma ) { int range_cnt_length; char range_cnt_str[SPIDER_SQL_INT_LEN]; - DBUG_ENTER("spider_mysql_handler::append_multi_range_cnt"); + DBUG_ENTER("spider_mbase_handler::append_multi_range_cnt"); DBUG_PRINT("info",("spider this=%p", this)); range_cnt_length = my_sprintf(range_cnt_str, (range_cnt_str, "%u", multi_range_cnt)); @@ -10075,13 +10338,13 @@ int spider_mysql_handler::append_multi_range_cnt( DBUG_RETURN(0); } -int spider_mysql_handler::append_multi_range_cnt_with_name_part( +int spider_mbase_handler::append_multi_range_cnt_with_name_part( ulong sql_type, uint multi_range_cnt ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_multi_range_cnt_with_name_part"); + DBUG_ENTER("spider_mbase_handler::append_multi_range_cnt_with_name_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10098,13 +10361,13 @@ int spider_mysql_handler::append_multi_range_cnt_with_name_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_multi_range_cnt_with_name( +int spider_mbase_handler::append_multi_range_cnt_with_name( spider_string *str, uint multi_range_cnt ) { int range_cnt_length; char range_cnt_str[SPIDER_SQL_INT_LEN]; - DBUG_ENTER("spider_mysql_handler::append_multi_range_cnt_with_name"); + DBUG_ENTER("spider_mbase_handler::append_multi_range_cnt_with_name"); DBUG_PRINT("info",("spider this=%p", this)); range_cnt_length = my_sprintf(range_cnt_str, (range_cnt_str, "%u", multi_range_cnt)); @@ -10118,7 +10381,7 @@ int spider_mysql_handler::append_multi_range_cnt_with_name( DBUG_RETURN(0); } -int spider_mysql_handler::append_open_handler_part( +int spider_mbase_handler::append_open_handler_part( ulong sql_type, uint handler_id, SPIDER_CONN *conn, @@ -10126,7 +10389,7 @@ int spider_mysql_handler::append_open_handler_part( ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_open_handler_part"); + DBUG_ENTER("spider_mbase_handler::append_open_handler_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10141,14 +10404,14 @@ int spider_mysql_handler::append_open_handler_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_open_handler( +int spider_mbase_handler::append_open_handler( spider_string *str, uint handler_id, SPIDER_CONN *conn, int link_idx ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_open_handler"); + DBUG_ENTER("spider_mbase_handler::append_open_handler"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider link_idx=%d", link_idx)); DBUG_PRINT("info",("spider m_handler_cid=%s", @@ -10172,13 +10435,13 @@ int spider_mysql_handler::append_open_handler( DBUG_RETURN(0); } -int spider_mysql_handler::append_close_handler_part( +int spider_mbase_handler::append_close_handler_part( ulong sql_type, int link_idx ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_close_handler_part"); + DBUG_ENTER("spider_mbase_handler::append_close_handler_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10193,11 +10456,11 @@ int spider_mysql_handler::append_close_handler_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_close_handler( +int spider_mbase_handler::append_close_handler( spider_string *str, int link_idx ) { - DBUG_ENTER("spider_mysql_handler::append_close_handler"); + DBUG_ENTER("spider_mbase_handler::append_close_handler"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_HANDLER_LEN + SPIDER_SQL_CLOSE_LEN + SPIDER_SQL_HANDLER_CID_LEN)) @@ -10209,12 +10472,12 @@ int spider_mysql_handler::append_close_handler( DBUG_RETURN(0); } -int spider_mysql_handler::append_insert_terminator_part( +int spider_mbase_handler::append_insert_terminator_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_insert_terminator_part"); + DBUG_ENTER("spider_mbase_handler::append_insert_terminator_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10228,10 +10491,10 @@ int spider_mysql_handler::append_insert_terminator_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_insert_terminator( +int spider_mbase_handler::append_insert_terminator( spider_string *str ) { - DBUG_ENTER("spider_mysql_handler::append_insert_terminator"); + DBUG_ENTER("spider_mbase_handler::append_insert_terminator"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider dup_update_sql.length=%u", dup_update_sql.length())); if ( @@ -10256,12 +10519,12 @@ int spider_mysql_handler::append_insert_terminator( DBUG_RETURN(0); } -int spider_mysql_handler::append_insert_values_part( +int spider_mbase_handler::append_insert_values_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_insert_values_part"); + DBUG_ENTER("spider_mbase_handler::append_insert_values_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10275,14 +10538,14 @@ int spider_mysql_handler::append_insert_values_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_insert_values( +int spider_mbase_handler::append_insert_values( spider_string *str ) { SPIDER_SHARE *share = spider->share; TABLE *table = spider->get_table(); Field **field; bool add_value = FALSE; - DBUG_ENTER("spider_mysql_handler::append_insert_values"); + DBUG_ENTER("spider_mbase_handler::append_insert_values"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_OPEN_PAREN_LEN)) { @@ -10329,7 +10592,7 @@ int spider_mysql_handler::append_insert_values( str->q_append(SPIDER_SQL_NULL_STR, SPIDER_SQL_NULL_LEN); } else { if ( - spider_db_mysql_utility. + spider_db_mbase_utility-> append_column_value(spider, str, *field, NULL, share->access_charset) || str->reserve(SPIDER_SQL_COMMA_LEN) @@ -10359,12 +10622,12 @@ int spider_mysql_handler::append_insert_values( DBUG_RETURN(0); } -int spider_mysql_handler::append_into_part( +int spider_mbase_handler::append_into_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_into_part"); + DBUG_ENTER("spider_mbase_handler::append_into_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10378,13 +10641,13 @@ int spider_mysql_handler::append_into_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_into( +int spider_mbase_handler::append_into( spider_string *str ) { const TABLE *table = spider->get_table(); Field **field; uint field_name_length = 0; - DBUG_ENTER("spider_mysql_handler::append_into"); + DBUG_ENTER("spider_mbase_handler::append_into"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_INTO_LEN + mysql_share->db_nm_max_length + SPIDER_SQL_DOT_LEN + mysql_share->table_nm_max_length + @@ -10420,10 +10683,10 @@ int spider_mysql_handler::append_into( DBUG_RETURN(0); } -void spider_mysql_handler::set_insert_to_pos( +void spider_mbase_handler::set_insert_to_pos( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::set_insert_to_pos"); + DBUG_ENTER("spider_mbase_handler::set_insert_to_pos"); switch (sql_type) { case SPIDER_SQL_TYPE_INSERT_SQL: @@ -10436,13 +10699,13 @@ void spider_mysql_handler::set_insert_to_pos( DBUG_VOID_RETURN; } -int spider_mysql_handler::append_from_part( +int spider_mbase_handler::append_from_part( ulong sql_type, int link_idx ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_from_part"); + DBUG_ENTER("spider_mbase_handler::append_from_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10462,12 +10725,12 @@ int spider_mysql_handler::append_from_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_from( +int spider_mbase_handler::append_from( spider_string *str, ulong sql_type, int link_idx ) { - DBUG_ENTER("spider_mysql_handler::append_from"); + DBUG_ENTER("spider_mbase_handler::append_from"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider link_idx=%d", link_idx)); int error_num = 0; @@ -10501,14 +10764,14 @@ int spider_mysql_handler::append_from( DBUG_RETURN(0); } -int spider_mysql_handler::append_flush_tables_part( +int spider_mbase_handler::append_flush_tables_part( ulong sql_type, int link_idx, bool lock ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_flush_tables_part"); + DBUG_ENTER("spider_mbase_handler::append_flush_tables_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10522,12 +10785,12 @@ int spider_mysql_handler::append_flush_tables_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_flush_tables( +int spider_mbase_handler::append_flush_tables( spider_string *str, int link_idx, bool lock ) { - DBUG_ENTER("spider_mysql_handler::append_flush_tables"); + DBUG_ENTER("spider_mbase_handler::append_flush_tables"); DBUG_PRINT("info",("spider this=%p", this)); if (lock) { @@ -10545,13 +10808,13 @@ int spider_mysql_handler::append_flush_tables( DBUG_RETURN(0); } -int spider_mysql_handler::append_optimize_table_part( +int spider_mbase_handler::append_optimize_table_part( ulong sql_type, int link_idx ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_optimize_table_part"); + DBUG_ENTER("spider_mbase_handler::append_optimize_table_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10565,7 +10828,7 @@ int spider_mysql_handler::append_optimize_table_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_optimize_table( +int spider_mbase_handler::append_optimize_table( spider_string *str, int link_idx ) { @@ -10573,7 +10836,7 @@ int spider_mysql_handler::append_optimize_table( int conn_link_idx = spider->conn_link_idx[link_idx]; int local_length = spider_param_internal_optimize_local(spider->trx->thd, share->internal_optimize_local) * SPIDER_SQL_SQL_LOCAL_LEN; - DBUG_ENTER("spider_mysql_handler::append_optimize_table"); + DBUG_ENTER("spider_mbase_handler::append_optimize_table"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SQL_OPTIMIZE_LEN + SPIDER_SQL_SQL_TABLE_LEN + local_length + @@ -10590,13 +10853,13 @@ int spider_mysql_handler::append_optimize_table( DBUG_RETURN(0); } -int spider_mysql_handler::append_analyze_table_part( +int spider_mbase_handler::append_analyze_table_part( ulong sql_type, int link_idx ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_analyze_table_part"); + DBUG_ENTER("spider_mbase_handler::append_analyze_table_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10610,7 +10873,7 @@ int spider_mysql_handler::append_analyze_table_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_analyze_table( +int spider_mbase_handler::append_analyze_table( spider_string *str, int link_idx ) { @@ -10618,7 +10881,7 @@ int spider_mysql_handler::append_analyze_table( int conn_link_idx = spider->conn_link_idx[link_idx]; int local_length = spider_param_internal_optimize_local(spider->trx->thd, share->internal_optimize_local) * SPIDER_SQL_SQL_LOCAL_LEN; - DBUG_ENTER("spider_mysql_handler::append_analyze_table"); + DBUG_ENTER("spider_mbase_handler::append_analyze_table"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SQL_ANALYZE_LEN + SPIDER_SQL_SQL_TABLE_LEN + local_length + @@ -10635,14 +10898,14 @@ int spider_mysql_handler::append_analyze_table( DBUG_RETURN(0); } -int spider_mysql_handler::append_repair_table_part( +int spider_mbase_handler::append_repair_table_part( ulong sql_type, int link_idx, HA_CHECK_OPT* check_opt ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_repair_table_part"); + DBUG_ENTER("spider_mbase_handler::append_repair_table_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10656,7 +10919,7 @@ int spider_mysql_handler::append_repair_table_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_repair_table( +int spider_mbase_handler::append_repair_table( spider_string *str, int link_idx, HA_CHECK_OPT* check_opt @@ -10665,7 +10928,7 @@ int spider_mysql_handler::append_repair_table( int conn_link_idx = spider->conn_link_idx[link_idx]; int local_length = spider_param_internal_optimize_local(spider->trx->thd, share->internal_optimize_local) * SPIDER_SQL_SQL_LOCAL_LEN; - DBUG_ENTER("spider_mysql_handler::append_repair_table"); + DBUG_ENTER("spider_mbase_handler::append_repair_table"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SQL_REPAIR_LEN + SPIDER_SQL_SQL_TABLE_LEN + local_length + @@ -10700,14 +10963,14 @@ int spider_mysql_handler::append_repair_table( DBUG_RETURN(0); } -int spider_mysql_handler::append_check_table_part( +int spider_mbase_handler::append_check_table_part( ulong sql_type, int link_idx, HA_CHECK_OPT* check_opt ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_check_table_part"); + DBUG_ENTER("spider_mbase_handler::append_check_table_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10721,13 +10984,13 @@ int spider_mysql_handler::append_check_table_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_check_table( +int spider_mbase_handler::append_check_table( spider_string *str, int link_idx, HA_CHECK_OPT* check_opt ) { int conn_link_idx = spider->conn_link_idx[link_idx]; - DBUG_ENTER("spider_mysql_handler::append_check_table"); + DBUG_ENTER("spider_mbase_handler::append_check_table"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SQL_CHECK_TABLE_LEN + mysql_share->db_names_str[conn_link_idx].length() + @@ -10765,13 +11028,13 @@ int spider_mysql_handler::append_check_table( DBUG_RETURN(0); } -int spider_mysql_handler::append_enable_keys_part( +int spider_mbase_handler::append_enable_keys_part( ulong sql_type, int link_idx ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_enable_keys_part"); + DBUG_ENTER("spider_mbase_handler::append_enable_keys_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10785,12 +11048,12 @@ int spider_mysql_handler::append_enable_keys_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_enable_keys( +int spider_mbase_handler::append_enable_keys( spider_string *str, int link_idx ) { int conn_link_idx = spider->conn_link_idx[link_idx]; - DBUG_ENTER("spider_mysql_handler::append_enable_keys"); + DBUG_ENTER("spider_mbase_handler::append_enable_keys"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SQL_ALTER_TABLE_LEN + mysql_share->db_names_str[conn_link_idx].length() + @@ -10806,13 +11069,13 @@ int spider_mysql_handler::append_enable_keys( DBUG_RETURN(0); } -int spider_mysql_handler::append_disable_keys_part( +int spider_mbase_handler::append_disable_keys_part( ulong sql_type, int link_idx ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_disable_keys_part"); + DBUG_ENTER("spider_mbase_handler::append_disable_keys_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10826,12 +11089,12 @@ int spider_mysql_handler::append_disable_keys_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_disable_keys( +int spider_mbase_handler::append_disable_keys( spider_string *str, int link_idx ) { int conn_link_idx = spider->conn_link_idx[link_idx]; - DBUG_ENTER("spider_mysql_handler::append_disable_keys"); + DBUG_ENTER("spider_mbase_handler::append_disable_keys"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_SQL_ALTER_TABLE_LEN + mysql_share->db_names_str[conn_link_idx].length() + @@ -10847,12 +11110,12 @@ int spider_mysql_handler::append_disable_keys( DBUG_RETURN(0); } -int spider_mysql_handler::append_delete_all_rows_part( +int spider_mbase_handler::append_delete_all_rows_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_delete_all_rows_part"); + DBUG_ENTER("spider_mbase_handler::append_delete_all_rows_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10866,12 +11129,12 @@ int spider_mysql_handler::append_delete_all_rows_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_delete_all_rows( +int spider_mbase_handler::append_delete_all_rows( spider_string *str, ulong sql_type ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_delete_all_rows"); + DBUG_ENTER("spider_mbase_handler::append_delete_all_rows"); DBUG_PRINT("info",("spider this=%p", this)); if (spider->sql_command == SQLCOM_TRUNCATE) { @@ -10887,12 +11150,12 @@ int spider_mysql_handler::append_delete_all_rows( DBUG_RETURN(0); } -int spider_mysql_handler::append_truncate( +int spider_mbase_handler::append_truncate( spider_string *str, ulong sql_type, int link_idx ) { - DBUG_ENTER("spider_mysql_handler::append_truncate"); + DBUG_ENTER("spider_mbase_handler::append_truncate"); if (str->reserve(SPIDER_SQL_TRUNCATE_TABLE_LEN + mysql_share->db_nm_max_length + SPIDER_SQL_DOT_LEN + mysql_share->table_nm_max_length + @@ -10904,7 +11167,7 @@ int spider_mysql_handler::append_truncate( DBUG_RETURN(0); } -int spider_mysql_handler::append_explain_select_part( +int spider_mbase_handler::append_explain_select_part( key_range *start_key, key_range *end_key, ulong sql_type, @@ -10912,7 +11175,7 @@ int spider_mysql_handler::append_explain_select_part( ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_explain_select_part"); + DBUG_ENTER("spider_mbase_handler::append_explain_select_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -10927,7 +11190,7 @@ int spider_mysql_handler::append_explain_select_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_explain_select( +int spider_mbase_handler::append_explain_select( spider_string *str, key_range *start_key, key_range *end_key, @@ -10935,7 +11198,7 @@ int spider_mysql_handler::append_explain_select( int link_idx ) { int error_num; - DBUG_ENTER("spider_mysql_handler::append_explain_select"); + DBUG_ENTER("spider_mbase_handler::append_explain_select"); DBUG_PRINT("info",("spider this=%p", this)); if (str->reserve(SPIDER_SQL_EXPLAIN_SELECT_LEN)) { @@ -10964,7 +11227,7 @@ int spider_mysql_handler::append_explain_select( * solely of the specified column. * FALSE - otherwise. ********************************************************************/ -bool spider_mysql_handler::is_sole_projection_field( +bool spider_mbase_handler::is_sole_projection_field( uint16 field_index ) { // Determine whether the projection list consists solely of the field of interest @@ -10973,7 +11236,7 @@ bool spider_mysql_handler::is_sole_projection_field( uint16 projection_field_count = 0; uint16 projection_field_index; Field** field; - DBUG_ENTER( "spider_mysql_handler::is_sole_projection_field" ); + DBUG_ENTER( "spider_mbase_handler::is_sole_projection_field" ); for ( field = table->field; *field ; field++ ) { @@ -11012,10 +11275,10 @@ bool spider_mysql_handler::is_sole_projection_field( DBUG_RETURN( FALSE ); } -bool spider_mysql_handler::is_bulk_insert_exec_period( +bool spider_mbase_handler::is_bulk_insert_exec_period( bool bulk_end ) { - DBUG_ENTER("spider_mysql_handler::is_bulk_insert_exec_period"); + DBUG_ENTER("spider_mbase_handler::is_bulk_insert_exec_period"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider insert_sql.length=%u", insert_sql.length())); DBUG_PRINT("info",("spider insert_pos=%d", insert_pos)); @@ -11029,19 +11292,19 @@ bool spider_mysql_handler::is_bulk_insert_exec_period( DBUG_RETURN(FALSE); } -bool spider_mysql_handler::sql_is_filled_up( +bool spider_mbase_handler::sql_is_filled_up( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::sql_is_filled_up"); + DBUG_ENTER("spider_mbase_handler::sql_is_filled_up"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(filled_up); } -bool spider_mysql_handler::sql_is_empty( +bool spider_mbase_handler::sql_is_empty( ulong sql_type ) { bool is_empty; - DBUG_ENTER("spider_mysql_handler::sql_is_empty"); + DBUG_ENTER("spider_mbase_handler::sql_is_empty"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -11069,34 +11332,34 @@ bool spider_mysql_handler::sql_is_empty( DBUG_RETURN(is_empty); } -bool spider_mysql_handler::support_multi_split_read() +bool spider_mbase_handler::support_multi_split_read() { - DBUG_ENTER("spider_mysql_handler::support_multi_split_read"); + DBUG_ENTER("spider_mbase_handler::support_multi_split_read"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(TRUE); } -bool spider_mysql_handler::support_bulk_update() +bool spider_mbase_handler::support_bulk_update() { - DBUG_ENTER("spider_mysql_handler::support_bulk_update"); + DBUG_ENTER("spider_mbase_handler::support_bulk_update"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(TRUE); } -int spider_mysql_handler::bulk_tmp_table_insert() +int spider_mbase_handler::bulk_tmp_table_insert() { int error_num; - DBUG_ENTER("spider_mysql_handler::bulk_tmp_table_insert"); + DBUG_ENTER("spider_mbase_handler::bulk_tmp_table_insert"); DBUG_PRINT("info",("spider this=%p", this)); error_num = store_sql_to_bulk_tmp_table(&update_sql, upd_tmp_tbl); DBUG_RETURN(error_num); } -int spider_mysql_handler::bulk_tmp_table_insert( +int spider_mbase_handler::bulk_tmp_table_insert( int link_idx ) { int error_num; - DBUG_ENTER("spider_mysql_handler::bulk_tmp_table_insert"); + DBUG_ENTER("spider_mbase_handler::bulk_tmp_table_insert"); DBUG_PRINT("info",("spider this=%p", this)); error_num = store_sql_to_bulk_tmp_table( &spider->result_list.update_sqls[link_idx], @@ -11104,10 +11367,10 @@ int spider_mysql_handler::bulk_tmp_table_insert( DBUG_RETURN(error_num); } -int spider_mysql_handler::bulk_tmp_table_end_bulk_insert() +int spider_mbase_handler::bulk_tmp_table_end_bulk_insert() { int error_num; - DBUG_ENTER("spider_mysql_handler::bulk_tmp_table_end_bulk_insert"); + DBUG_ENTER("spider_mbase_handler::bulk_tmp_table_end_bulk_insert"); DBUG_PRINT("info",("spider this=%p", this)); if ((error_num = upd_tmp_tbl->file->ha_end_bulk_insert())) { @@ -11116,10 +11379,10 @@ int spider_mysql_handler::bulk_tmp_table_end_bulk_insert() DBUG_RETURN(0); } -int spider_mysql_handler::bulk_tmp_table_rnd_init() +int spider_mbase_handler::bulk_tmp_table_rnd_init() { int error_num; - DBUG_ENTER("spider_mysql_handler::bulk_tmp_table_rnd_init"); + DBUG_ENTER("spider_mbase_handler::bulk_tmp_table_rnd_init"); DBUG_PRINT("info",("spider this=%p", this)); upd_tmp_tbl->file->extra(HA_EXTRA_CACHE); if ((error_num = upd_tmp_tbl->file->ha_rnd_init(TRUE))) @@ -11130,10 +11393,10 @@ int spider_mysql_handler::bulk_tmp_table_rnd_init() DBUG_RETURN(0); } -int spider_mysql_handler::bulk_tmp_table_rnd_next() +int spider_mbase_handler::bulk_tmp_table_rnd_next() { int error_num; - DBUG_ENTER("spider_mysql_handler::bulk_tmp_table_rnd_next"); + DBUG_ENTER("spider_mbase_handler::bulk_tmp_table_rnd_next"); DBUG_PRINT("info",("spider this=%p", this)); #if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 50200 error_num = upd_tmp_tbl->file->ha_rnd_next(upd_tmp_tbl->record[0]); @@ -11147,10 +11410,10 @@ int spider_mysql_handler::bulk_tmp_table_rnd_next() DBUG_RETURN(error_num); } -int spider_mysql_handler::bulk_tmp_table_rnd_end() +int spider_mbase_handler::bulk_tmp_table_rnd_end() { int error_num; - DBUG_ENTER("spider_mysql_handler::bulk_tmp_table_rnd_end"); + DBUG_ENTER("spider_mbase_handler::bulk_tmp_table_rnd_end"); DBUG_PRINT("info",("spider this=%p", this)); reading_from_bulk_tmp_table = FALSE; if ((error_num = upd_tmp_tbl->file->ha_rnd_end())) @@ -11160,28 +11423,28 @@ int spider_mysql_handler::bulk_tmp_table_rnd_end() DBUG_RETURN(0); } -bool spider_mysql_handler::need_copy_for_update( +bool spider_mbase_handler::need_copy_for_update( int link_idx ) { int all_link_idx = spider->conn_link_idx[link_idx]; - DBUG_ENTER("spider_mysql_handler::need_copy_for_update"); + DBUG_ENTER("spider_mbase_handler::need_copy_for_update"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(!mysql_share->same_db_table_name || spider->share->link_statuses[all_link_idx] == SPIDER_LINK_STATUS_RECOVERY); } -bool spider_mysql_handler::bulk_tmp_table_created() +bool spider_mbase_handler::bulk_tmp_table_created() { - DBUG_ENTER("spider_mysql_handler::bulk_tmp_table_created"); + DBUG_ENTER("spider_mbase_handler::bulk_tmp_table_created"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(upd_tmp_tbl); } -int spider_mysql_handler::mk_bulk_tmp_table_and_bulk_start() +int spider_mbase_handler::mk_bulk_tmp_table_and_bulk_start() { THD *thd = spider->trx->thd; TABLE *table = spider->get_table(); - DBUG_ENTER("spider_mysql_handler::mk_bulk_tmp_table_and_bulk_start"); + DBUG_ENTER("spider_mbase_handler::mk_bulk_tmp_table_and_bulk_start"); DBUG_PRINT("info",("spider this=%p", this)); if (!upd_tmp_tbl) { @@ -11202,9 +11465,9 @@ int spider_mysql_handler::mk_bulk_tmp_table_and_bulk_start() DBUG_RETURN(0); } -void spider_mysql_handler::rm_bulk_tmp_table() +void spider_mbase_handler::rm_bulk_tmp_table() { - DBUG_ENTER("spider_mysql_handler::rm_bulk_tmp_table"); + DBUG_ENTER("spider_mbase_handler::rm_bulk_tmp_table"); DBUG_PRINT("info",("spider this=%p", this)); if (upd_tmp_tbl) { @@ -11214,12 +11477,12 @@ void spider_mysql_handler::rm_bulk_tmp_table() DBUG_VOID_RETURN; } -int spider_mysql_handler::store_sql_to_bulk_tmp_table( +int spider_mbase_handler::store_sql_to_bulk_tmp_table( spider_string *str, TABLE *tmp_table ) { int error_num; - DBUG_ENTER("spider_mysql_handler::store_sql_to_bulk_tmp_table"); + DBUG_ENTER("spider_mbase_handler::store_sql_to_bulk_tmp_table"); DBUG_PRINT("info",("spider this=%p", this)); tmp_table->field[0]->set_notnull(); tmp_table->field[0]->store(str->ptr(), str->length(), str->charset()); @@ -11228,24 +11491,24 @@ int spider_mysql_handler::store_sql_to_bulk_tmp_table( DBUG_RETURN(0); } -int spider_mysql_handler::restore_sql_from_bulk_tmp_table( +int spider_mbase_handler::restore_sql_from_bulk_tmp_table( spider_string *str, TABLE *tmp_table ) { - DBUG_ENTER("spider_mysql_handler::restore_sql_from_bulk_tmp_table"); + DBUG_ENTER("spider_mbase_handler::restore_sql_from_bulk_tmp_table"); DBUG_PRINT("info",("spider this=%p", this)); tmp_table->field[0]->val_str(str->get_str()); str->mem_calc(); DBUG_RETURN(0); } -int spider_mysql_handler::insert_lock_tables_list( +int spider_mbase_handler::insert_lock_tables_list( SPIDER_CONN *conn, int link_idx ) { - spider_db_mysql *db_conn = (spider_db_mysql *) conn->db_conn; + spider_db_mbase *db_conn = (spider_db_mbase *) conn->db_conn; SPIDER_LINK_FOR_HASH *tmp_link_for_hash2 = &link_for_hash[link_idx]; - DBUG_ENTER("spider_mysql_handler::insert_lock_tables_list"); + DBUG_ENTER("spider_mbase_handler::insert_lock_tables_list"); DBUG_PRINT("info",("spider this=%p", this)); uint old_elements = db_conn->lock_table_hash.array.max_element; @@ -11271,7 +11534,7 @@ int spider_mysql_handler::insert_lock_tables_list( DBUG_RETURN(0); } -int spider_mysql_handler::append_lock_tables_list( +int spider_mbase_handler::append_lock_tables_list( SPIDER_CONN *conn, int link_idx, int *appended @@ -11279,8 +11542,8 @@ int spider_mysql_handler::append_lock_tables_list( int error_num; SPIDER_LINK_FOR_HASH *tmp_link_for_hash, *tmp_link_for_hash2; int conn_link_idx = spider->conn_link_idx[link_idx]; - spider_db_mysql *db_conn = (spider_db_mysql *) conn->db_conn; - DBUG_ENTER("spider_mysql_handler::append_lock_tables_list"); + spider_db_mbase *db_conn = (spider_db_mbase *) conn->db_conn; + DBUG_ENTER("spider_mbase_handler::append_lock_tables_list"); DBUG_PRINT("info",("spider this=%p", this)); tmp_link_for_hash2 = &link_for_hash[link_idx]; tmp_link_for_hash2->db_table_str = @@ -11342,14 +11605,14 @@ int spider_mysql_handler::append_lock_tables_list( DBUG_RETURN(0); } -int spider_mysql_handler::realloc_sql( +int spider_mbase_handler::realloc_sql( ulong *realloced ) { THD *thd = spider->trx->thd; st_spider_share *share = spider->share; int init_sql_alloc_size = spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size); - DBUG_ENTER("spider_mysql_handler::realloc_sql"); + DBUG_ENTER("spider_mbase_handler::realloc_sql"); DBUG_PRINT("info",("spider this=%p", this)); if ((int) sql.alloced_length() > init_sql_alloc_size * 2) { @@ -11396,10 +11659,10 @@ int spider_mysql_handler::realloc_sql( DBUG_RETURN(0); } -int spider_mysql_handler::reset_sql( +int spider_mbase_handler::reset_sql( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::reset_sql"); + DBUG_ENTER("spider_mbase_handler::reset_sql"); DBUG_PRINT("info",("spider this=%p", this)); if (sql_type & SPIDER_SQL_TYPE_SELECT_SQL) { @@ -11426,73 +11689,73 @@ int spider_mysql_handler::reset_sql( } #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) -int spider_mysql_handler::reset_keys( +int spider_mbase_handler::reset_keys( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::reset_keys"); + DBUG_ENTER("spider_mbase_handler::reset_keys"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_RETURN(0); } -int spider_mysql_handler::reset_upds( +int spider_mbase_handler::reset_upds( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::reset_upds"); + DBUG_ENTER("spider_mbase_handler::reset_upds"); DBUG_PRINT("info",("spider this=%p", this)); hs_upds.clear(); DBUG_RETURN(0); } -int spider_mysql_handler::reset_strs( +int spider_mbase_handler::reset_strs( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::reset_strs"); + DBUG_ENTER("spider_mbase_handler::reset_strs"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_RETURN(0); } -int spider_mysql_handler::reset_strs_pos( +int spider_mbase_handler::reset_strs_pos( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::reset_strs_pos"); + DBUG_ENTER("spider_mbase_handler::reset_strs_pos"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_ASSERT(0); DBUG_RETURN(0); } -int spider_mysql_handler::push_back_upds( +int spider_mbase_handler::push_back_upds( SPIDER_HS_STRING_REF &info ) { int error_num; - DBUG_ENTER("spider_mysql_handler::push_back_upds"); + DBUG_ENTER("spider_mbase_handler::push_back_upds"); DBUG_PRINT("info",("spider this=%p", this)); error_num = hs_upds.push_back(info); DBUG_RETURN(error_num); } #endif -bool spider_mysql_handler::need_lock_before_set_sql_for_exec( +bool spider_mbase_handler::need_lock_before_set_sql_for_exec( ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::need_lock_before_set_sql_for_exec"); + DBUG_ENTER("spider_mbase_handler::need_lock_before_set_sql_for_exec"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(FALSE); } #ifdef SPIDER_HAS_GROUP_BY_HANDLER -int spider_mysql_handler::set_sql_for_exec( +int spider_mbase_handler::set_sql_for_exec( ulong sql_type, int link_idx, SPIDER_LINK_IDX_CHAIN *link_idx_chain ) { int error_num; - DBUG_ENTER("spider_mysql_handler::set_sql_for_exec"); + DBUG_ENTER("spider_mbase_handler::set_sql_for_exec"); DBUG_PRINT("info",("spider this=%p", this)); if (sql_type & SPIDER_SQL_TYPE_SELECT_SQL) { - if ((error_num = spider_db_mysql_utility.reappend_tables( + if ((error_num = spider_db_mbase_utility->reappend_tables( spider->fields, link_idx_chain, &sql))) DBUG_RETURN(error_num); exec_sql = &sql; @@ -11501,7 +11764,7 @@ int spider_mysql_handler::set_sql_for_exec( } #endif -int spider_mysql_handler::set_sql_for_exec( +int spider_mbase_handler::set_sql_for_exec( ulong sql_type, int link_idx ) { @@ -11510,7 +11773,7 @@ int spider_mysql_handler::set_sql_for_exec( SPIDER_SHARE *share = spider->share; SPIDER_RESULT_LIST *result_list = &spider->result_list; int all_link_idx = spider->conn_link_idx[link_idx]; - DBUG_ENTER("spider_mysql_handler::set_sql_for_exec"); + DBUG_ENTER("spider_mbase_handler::set_sql_for_exec"); DBUG_PRINT("info",("spider this=%p", this)); if (sql_type & (SPIDER_SQL_TYPE_SELECT_SQL | SPIDER_SQL_TYPE_TMP_SQL)) { @@ -11561,7 +11824,7 @@ int spider_mysql_handler::set_sql_for_exec( exec_sql->length(table_name_pos); if (result_list->tmp_table_join && spider->bka_mode != 2) { - if ((error_num = spider_db_mysql_utility.append_from_with_alias( + if ((error_num = spider_db_mbase_utility->append_from_with_alias( exec_sql, table_names, table_name_lengths, table_aliases, table_alias_lengths, 2, &table_name_pos, TRUE)) @@ -11683,12 +11946,12 @@ int spider_mysql_handler::set_sql_for_exec( DBUG_RETURN(0); } -int spider_mysql_handler::set_sql_for_exec( +int spider_mbase_handler::set_sql_for_exec( spider_db_copy_table *tgt_ct, ulong sql_type ) { - spider_mysql_copy_table *mysql_ct = (spider_mysql_copy_table *) tgt_ct; - DBUG_ENTER("spider_mysql_handler::set_sql_for_exec"); + spider_mbase_copy_table *mysql_ct = (spider_mbase_copy_table *) tgt_ct; + DBUG_ENTER("spider_mbase_handler::set_sql_for_exec"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -11702,7 +11965,7 @@ int spider_mysql_handler::set_sql_for_exec( DBUG_RETURN(0); } -int spider_mysql_handler::execute_sql( +int spider_mbase_handler::execute_sql( ulong sql_type, SPIDER_CONN *conn, int quick_mode, @@ -11710,7 +11973,7 @@ int spider_mysql_handler::execute_sql( ) { spider_string *tgt_sql; uint tgt_length; - DBUG_ENTER("spider_mysql_handler::execute_sql"); + DBUG_ENTER("spider_mbase_handler::execute_sql"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -11764,23 +12027,23 @@ int spider_mysql_handler::execute_sql( )); } -int spider_mysql_handler::reset() +int spider_mbase_handler::reset() { - DBUG_ENTER("spider_mysql_handler::reset"); + DBUG_ENTER("spider_mbase_handler::reset"); DBUG_PRINT("info",("spider this=%p", this)); update_sql.length(0); DBUG_RETURN(0); } -int spider_mysql_handler::sts_mode_exchange( +int spider_mbase_handler::sts_mode_exchange( int sts_mode ) { - DBUG_ENTER("spider_mysql_handler::sts_mode_exchange"); + DBUG_ENTER("spider_mbase_handler::sts_mode_exchange"); DBUG_PRINT("info",("spider sts_mode=%d", sts_mode)); DBUG_RETURN(sts_mode); } -int spider_mysql_handler::show_table_status( +int spider_mbase_handler::show_table_status( int link_idx, int sts_mode, uint flag @@ -11791,7 +12054,7 @@ int spider_mysql_handler::show_table_status( SPIDER_SHARE *share = spider->share; uint pos = (2 * spider->conn_link_idx[link_idx]); ulonglong auto_increment_value = 0; - DBUG_ENTER("spider_mysql_handler::show_table_status"); + DBUG_ENTER("spider_mbase_handler::show_table_status"); DBUG_PRINT("info",("spider sts_mode=%d", sts_mode)); if (sts_mode == 1) @@ -12087,15 +12350,15 @@ int spider_mysql_handler::show_table_status( DBUG_RETURN(0); } -int spider_mysql_handler::crd_mode_exchange( +int spider_mbase_handler::crd_mode_exchange( int crd_mode ) { - DBUG_ENTER("spider_mysql_handler::crd_mode_exchange"); + DBUG_ENTER("spider_mbase_handler::crd_mode_exchange"); DBUG_PRINT("info",("spider crd_mode=%d", crd_mode)); DBUG_RETURN(crd_mode); } -int spider_mysql_handler::show_index( +int spider_mbase_handler::show_index( int link_idx, int crd_mode ) { @@ -12107,7 +12370,7 @@ int spider_mysql_handler::show_index( int roop_count; longlong *tmp_cardinality; uint pos = (2 * spider->conn_link_idx[link_idx]); - DBUG_ENTER("spider_mysql_handler::show_index"); + DBUG_ENTER("spider_mbase_handler::show_index"); DBUG_PRINT("info",("spider crd_mode=%d", crd_mode)); if (crd_mode == 1) { @@ -12380,7 +12643,7 @@ int spider_mysql_handler::show_index( DBUG_RETURN(0); } -int spider_mysql_handler::show_records( +int spider_mbase_handler::show_records( int link_idx ) { int error_num; @@ -12388,7 +12651,7 @@ int spider_mysql_handler::show_records( SPIDER_DB_RESULT *res; SPIDER_SHARE *share = spider->share; uint pos = spider->conn_link_idx[link_idx]; - DBUG_ENTER("spider_mysql_handler::show_records"); + DBUG_ENTER("spider_mbase_handler::show_records"); pthread_mutex_lock(&conn->mta_conn_mutex); SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos); conn->need_mon = &spider->need_mons[link_idx]; @@ -12493,17 +12756,17 @@ int spider_mysql_handler::show_records( DBUG_RETURN(0); } -int spider_mysql_handler::show_last_insert_id( +int spider_mbase_handler::show_last_insert_id( int link_idx, ulonglong &last_insert_id ) { SPIDER_CONN *conn = spider->conns[link_idx]; - DBUG_ENTER("spider_mysql_handler::show_last_insert_id"); + DBUG_ENTER("spider_mbase_handler::show_last_insert_id"); last_insert_id = conn->db_conn->last_insert_id(); DBUG_RETURN(0); } -ha_rows spider_mysql_handler::explain_select( +ha_rows spider_mbase_handler::explain_select( key_range *start_key, key_range *end_key, int link_idx @@ -12515,7 +12778,7 @@ ha_rows spider_mysql_handler::explain_select( SPIDER_DB_RESULT *res; ha_rows rows; spider_db_handler *dbton_hdl = spider->dbton_handler[conn->dbton_id]; - DBUG_ENTER("spider_mysql_handler::explain_select"); + DBUG_ENTER("spider_mbase_handler::explain_select"); if ((error_num = dbton_hdl->append_explain_select_part( start_key, end_key, SPIDER_SQL_TYPE_OTHER_SQL, link_idx))) { @@ -12639,13 +12902,13 @@ ha_rows spider_mysql_handler::explain_select( DBUG_RETURN(rows); } -int spider_mysql_handler::lock_tables( +int spider_mbase_handler::lock_tables( int link_idx ) { int error_num; SPIDER_CONN *conn = spider->conns[link_idx]; spider_string *str = &sql; - DBUG_ENTER("spider_mysql_handler::lock_tables"); + DBUG_ENTER("spider_mbase_handler::lock_tables"); str->length(0); if ((error_num = conn->db_conn->append_lock_tables(str))) { @@ -12692,12 +12955,12 @@ int spider_mysql_handler::lock_tables( DBUG_RETURN(0); } -int spider_mysql_handler::unlock_tables( +int spider_mbase_handler::unlock_tables( int link_idx ) { int error_num; SPIDER_CONN *conn = spider->conns[link_idx]; - DBUG_ENTER("spider_mysql_handler::unlock_tables"); + DBUG_ENTER("spider_mbase_handler::unlock_tables"); if (conn->table_locked) { spider_string *str = &sql; @@ -12728,14 +12991,14 @@ int spider_mysql_handler::unlock_tables( DBUG_RETURN(0); } -int spider_mysql_handler::disable_keys( +int spider_mbase_handler::disable_keys( SPIDER_CONN *conn, int link_idx ) { int error_num; SPIDER_SHARE *share = spider->share; spider_string *str = &spider->result_list.sqls[link_idx]; - DBUG_ENTER("spider_mysql_handler::disable_keys"); + DBUG_ENTER("spider_mbase_handler::disable_keys"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); if ((error_num = append_disable_keys_part(SPIDER_SQL_TYPE_OTHER_HS, @@ -12777,14 +13040,14 @@ int spider_mysql_handler::disable_keys( DBUG_RETURN(0); } -int spider_mysql_handler::enable_keys( +int spider_mbase_handler::enable_keys( SPIDER_CONN *conn, int link_idx ) { int error_num; SPIDER_SHARE *share = spider->share; spider_string *str = &spider->result_list.sqls[link_idx]; - DBUG_ENTER("spider_mysql_handler::enable_keys"); + DBUG_ENTER("spider_mbase_handler::enable_keys"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); if ((error_num = append_enable_keys_part(SPIDER_SQL_TYPE_OTHER_HS, @@ -12826,7 +13089,7 @@ int spider_mysql_handler::enable_keys( DBUG_RETURN(0); } -int spider_mysql_handler::check_table( +int spider_mbase_handler::check_table( SPIDER_CONN *conn, int link_idx, HA_CHECK_OPT* check_opt @@ -12834,7 +13097,7 @@ int spider_mysql_handler::check_table( int error_num; SPIDER_SHARE *share = spider->share; spider_string *str = &spider->result_list.sqls[link_idx]; - DBUG_ENTER("spider_mysql_handler::check_table"); + DBUG_ENTER("spider_mbase_handler::check_table"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); if ((error_num = append_check_table_part(SPIDER_SQL_TYPE_OTHER_HS, @@ -12876,7 +13139,7 @@ int spider_mysql_handler::check_table( DBUG_RETURN(0); } -int spider_mysql_handler::repair_table( +int spider_mbase_handler::repair_table( SPIDER_CONN *conn, int link_idx, HA_CHECK_OPT* check_opt @@ -12884,7 +13147,7 @@ int spider_mysql_handler::repair_table( int error_num; SPIDER_SHARE *share = spider->share; spider_string *str = &spider->result_list.sqls[link_idx]; - DBUG_ENTER("spider_mysql_handler::repair_table"); + DBUG_ENTER("spider_mbase_handler::repair_table"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); if ((error_num = append_repair_table_part(SPIDER_SQL_TYPE_OTHER_HS, @@ -12926,14 +13189,14 @@ int spider_mysql_handler::repair_table( DBUG_RETURN(0); } -int spider_mysql_handler::analyze_table( +int spider_mbase_handler::analyze_table( SPIDER_CONN *conn, int link_idx ) { int error_num; SPIDER_SHARE *share = spider->share; spider_string *str = &spider->result_list.sqls[link_idx]; - DBUG_ENTER("spider_mysql_handler::analyze_table"); + DBUG_ENTER("spider_mbase_handler::analyze_table"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); if ((error_num = append_analyze_table_part(SPIDER_SQL_TYPE_OTHER_HS, @@ -12975,14 +13238,14 @@ int spider_mysql_handler::analyze_table( DBUG_RETURN(0); } -int spider_mysql_handler::optimize_table( +int spider_mbase_handler::optimize_table( SPIDER_CONN *conn, int link_idx ) { int error_num; SPIDER_SHARE *share = spider->share; spider_string *str = &spider->result_list.sqls[link_idx]; - DBUG_ENTER("spider_mysql_handler::optimize_table"); + DBUG_ENTER("spider_mbase_handler::optimize_table"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); if ((error_num = append_optimize_table_part(SPIDER_SQL_TYPE_OTHER_HS, @@ -13024,7 +13287,7 @@ int spider_mysql_handler::optimize_table( DBUG_RETURN(0); } -int spider_mysql_handler::flush_tables( +int spider_mbase_handler::flush_tables( SPIDER_CONN *conn, int link_idx, bool lock @@ -13032,7 +13295,7 @@ int spider_mysql_handler::flush_tables( int error_num; SPIDER_SHARE *share = spider->share; spider_string *str = &spider->result_list.sqls[link_idx]; - DBUG_ENTER("spider_mysql_handler::flush_tables"); + DBUG_ENTER("spider_mbase_handler::flush_tables"); DBUG_PRINT("info",("spider this=%p", this)); str->length(0); if ((error_num = append_flush_tables_part(SPIDER_SQL_TYPE_OTHER_HS, @@ -13057,13 +13320,13 @@ int spider_mysql_handler::flush_tables( DBUG_RETURN(0); } -int spider_mysql_handler::flush_logs( +int spider_mbase_handler::flush_logs( SPIDER_CONN *conn, int link_idx ) { int error_num; SPIDER_SHARE *share = spider->share; - DBUG_ENTER("spider_mysql_handler::flush_logs"); + DBUG_ENTER("spider_mbase_handler::flush_logs"); DBUG_PRINT("info",("spider this=%p", this)); spider_conn_set_timeout_from_share(conn, link_idx, spider->trx->thd, share); @@ -13082,16 +13345,16 @@ int spider_mysql_handler::flush_logs( DBUG_RETURN(0); } -int spider_mysql_handler::insert_opened_handler( +int spider_mbase_handler::insert_opened_handler( SPIDER_CONN *conn, int link_idx ) { - spider_db_mysql *db_conn = (spider_db_mysql *) conn->db_conn; + spider_db_mbase *db_conn = (spider_db_mbase *) conn->db_conn; SPIDER_LINK_FOR_HASH *tmp_link_for_hash = &link_for_hash[link_idx]; DBUG_ASSERT(tmp_link_for_hash->spider == spider); DBUG_ASSERT(tmp_link_for_hash->link_idx == link_idx); uint old_elements = db_conn->handler_open_array.max_element; - DBUG_ENTER("spider_mysql_handler::insert_opened_handler"); + DBUG_ENTER("spider_mbase_handler::insert_opened_handler"); DBUG_PRINT("info",("spider this=%p", this)); if (insert_dynamic(&db_conn->handler_open_array, (uchar*) &tmp_link_for_hash)) @@ -13108,14 +13371,14 @@ int spider_mysql_handler::insert_opened_handler( DBUG_RETURN(0); } -int spider_mysql_handler::delete_opened_handler( +int spider_mbase_handler::delete_opened_handler( SPIDER_CONN *conn, int link_idx ) { - spider_db_mysql *db_conn = (spider_db_mysql *) conn->db_conn; + spider_db_mbase *db_conn = (spider_db_mbase *) conn->db_conn; uint roop_count, elements = db_conn->handler_open_array.elements; SPIDER_LINK_FOR_HASH *tmp_link_for_hash; - DBUG_ENTER("spider_mysql_handler::delete_opened_handler"); + DBUG_ENTER("spider_mbase_handler::delete_opened_handler"); DBUG_PRINT("info",("spider this=%p", this)); for (roop_count = 0; roop_count < elements; roop_count++) { @@ -13131,27 +13394,27 @@ int spider_mysql_handler::delete_opened_handler( DBUG_RETURN(0); } -int spider_mysql_handler::sync_from_clone_source( +int spider_mbase_handler::sync_from_clone_source( spider_db_handler *dbton_hdl ) { - DBUG_ENTER("spider_mysql_handler::sync_from_clone_source"); + DBUG_ENTER("spider_mbase_handler::sync_from_clone_source"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(0); } -bool spider_mysql_handler::support_use_handler( +bool spider_mbase_handler::support_use_handler( int use_handler ) { - DBUG_ENTER("spider_mysql_handler::support_use_handler"); + DBUG_ENTER("spider_mbase_handler::support_use_handler"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_RETURN(TRUE); } -void spider_mysql_handler::minimum_select_bitmap_create() +void spider_mbase_handler::minimum_select_bitmap_create() { TABLE *table = spider->get_table(); Field **field_p; - DBUG_ENTER("spider_mysql_handler::minimum_select_bitmap_create"); + DBUG_ENTER("spider_mbase_handler::minimum_select_bitmap_create"); DBUG_PRINT("info",("spider this=%p", this)); memset(minimum_select_bitmap, 0, no_bytes_in_map(table->read_set)); if ( @@ -13218,10 +13481,10 @@ void spider_mysql_handler::minimum_select_bitmap_create() DBUG_VOID_RETURN; } -bool spider_mysql_handler::minimum_select_bit_is_set( +bool spider_mbase_handler::minimum_select_bit_is_set( uint field_index ) { - DBUG_ENTER("spider_mysql_handler::minimum_select_bit_is_set"); + DBUG_ENTER("spider_mbase_handler::minimum_select_bit_is_set"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_PRINT("info",("spider field_index=%u", field_index)); DBUG_PRINT("info",("spider minimum_select_bitmap=%s", @@ -13230,12 +13493,12 @@ bool spider_mysql_handler::minimum_select_bit_is_set( DBUG_RETURN(spider_bit_is_set(minimum_select_bitmap, field_index)); } -void spider_mysql_handler::copy_minimum_select_bitmap( +void spider_mbase_handler::copy_minimum_select_bitmap( uchar *bitmap ) { int roop_count; TABLE *table = spider->get_table(); - DBUG_ENTER("spider_mysql_handler::copy_minimum_select_bitmap"); + DBUG_ENTER("spider_mbase_handler::copy_minimum_select_bitmap"); for (roop_count = 0; roop_count < (int) ((table->s->fields + 7) / 8); roop_count++) @@ -13249,9 +13512,9 @@ void spider_mysql_handler::copy_minimum_select_bitmap( DBUG_VOID_RETURN; } -int spider_mysql_handler::init_union_table_name_pos() +int spider_mbase_handler::init_union_table_name_pos() { - DBUG_ENTER("spider_mysql_handler::init_union_table_name_pos"); + DBUG_ENTER("spider_mbase_handler::init_union_table_name_pos"); DBUG_PRINT("info",("spider this=%p", this)); if (!union_table_name_pos_first) { @@ -13268,9 +13531,9 @@ int spider_mysql_handler::init_union_table_name_pos() DBUG_RETURN(0); } -int spider_mysql_handler::set_union_table_name_pos() +int spider_mbase_handler::set_union_table_name_pos() { - DBUG_ENTER("spider_mysql_handler::set_union_table_name_pos"); + DBUG_ENTER("spider_mbase_handler::set_union_table_name_pos"); DBUG_PRINT("info",("spider this=%p", this)); if (union_table_name_pos_current->tgt_num >= SPIDER_INT_HLD_TGT_SIZE) { @@ -13293,12 +13556,12 @@ int spider_mysql_handler::set_union_table_name_pos() DBUG_RETURN(0); } -int spider_mysql_handler::reset_union_table_name( +int spider_mbase_handler::reset_union_table_name( spider_string *str, int link_idx, ulong sql_type ) { - DBUG_ENTER("spider_mysql_handler::reset_union_table_name"); + DBUG_ENTER("spider_mbase_handler::reset_union_table_name"); DBUG_PRINT("info",("spider this=%p", this)); if (!union_table_name_pos_current) DBUG_RETURN(0); @@ -13321,7 +13584,7 @@ int spider_mysql_handler::reset_union_table_name( } #ifdef SPIDER_HAS_GROUP_BY_HANDLER -int spider_mysql_handler::append_from_and_tables_part( +int spider_mbase_handler::append_from_and_tables_part( spider_fields *fields, ulong sql_type ) { @@ -13329,7 +13592,7 @@ int spider_mysql_handler::append_from_and_tables_part( spider_string *str; SPIDER_TABLE_HOLDER *table_holder; TABLE_LIST *table_list; - DBUG_ENTER("spider_mysql_handler::append_from_and_tables_part"); + DBUG_ENTER("spider_mbase_handler::append_from_and_tables_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -13342,19 +13605,19 @@ int spider_mysql_handler::append_from_and_tables_part( fields->set_pos_to_first_table_holder(); table_holder = fields->get_next_table_holder(); table_list = table_holder->table->pos_in_table_list; - error_num = spider_db_mysql_utility.append_from_and_tables( + error_num = spider_db_mbase_utility->append_from_and_tables( table_holder->spider, fields, str, table_list, fields->get_table_count()); DBUG_RETURN(error_num); } -int spider_mysql_handler::reappend_tables_part( +int spider_mbase_handler::reappend_tables_part( spider_fields *fields, ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::reappend_tables_part"); + DBUG_ENTER("spider_mbase_handler::reappend_tables_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -13364,17 +13627,17 @@ int spider_mysql_handler::reappend_tables_part( default: DBUG_RETURN(0); } - error_num = spider_db_mysql_utility.reappend_tables(fields, + error_num = spider_db_mbase_utility->reappend_tables(fields, link_idx_chain, str); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_where_part( +int spider_mbase_handler::append_where_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_where_part"); + DBUG_ENTER("spider_mbase_handler::append_where_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -13384,16 +13647,16 @@ int spider_mysql_handler::append_where_part( default: DBUG_RETURN(0); } - error_num = spider_db_mysql_utility.append_where(str); + error_num = spider_db_mbase_utility->append_where(str); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_having_part( +int spider_mbase_handler::append_having_part( ulong sql_type ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_having_part"); + DBUG_ENTER("spider_mbase_handler::append_having_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -13403,11 +13666,11 @@ int spider_mysql_handler::append_having_part( default: DBUG_RETURN(0); } - error_num = spider_db_mysql_utility.append_having(str); + error_num = spider_db_mbase_utility->append_having(str); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_item_type_part( +int spider_mbase_handler::append_item_type_part( Item *item, const char *alias, uint alias_length, @@ -13417,7 +13680,7 @@ int spider_mysql_handler::append_item_type_part( ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_item_type_part"); + DBUG_ENTER("spider_mbase_handler::append_item_type_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -13428,11 +13691,11 @@ int spider_mysql_handler::append_item_type_part( DBUG_RETURN(0); } error_num = spider_db_print_item_type(item, NULL, spider, str, - alias, alias_length, spider_dbton_mysql.dbton_id, use_fields, fields); + alias, alias_length, dbton_id, use_fields, fields); DBUG_RETURN(error_num); } -int spider_mysql_handler::append_list_item_select_part( +int spider_mbase_handler::append_list_item_select_part( List *select, const char *alias, uint alias_length, @@ -13442,7 +13705,7 @@ int spider_mysql_handler::append_list_item_select_part( ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_list_item_select_part"); + DBUG_ENTER("spider_mbase_handler::append_list_item_select_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -13457,7 +13720,7 @@ int spider_mysql_handler::append_list_item_select_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_list_item_select( +int spider_mbase_handler::append_list_item_select( List *select, spider_string *str, const char *alias, @@ -13466,12 +13729,12 @@ int spider_mysql_handler::append_list_item_select( spider_fields *fields ) { int error_num; - uint dbton_id = spider_dbton_mysql.dbton_id, length; + uint32 length; List_iterator_fast it(*select); Item *item; Field *field; const char *item_name; - DBUG_ENTER("spider_mysql_handler::append_list_item_select"); + DBUG_ENTER("spider_mbase_handler::append_list_item_select"); DBUG_PRINT("info",("spider this=%p", this)); while ((item = it++)) { @@ -13495,7 +13758,7 @@ int spider_mysql_handler::append_list_item_select( )) DBUG_RETURN(HA_ERR_OUT_OF_MEM); str->q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN); - if ((error_num = spider_db_mysql_utility.append_name(str, + if ((error_num = spider_db_mbase_utility->append_name(str, item_name, length))) { DBUG_RETURN(error_num); @@ -13506,7 +13769,7 @@ int spider_mysql_handler::append_list_item_select( DBUG_RETURN(0); } -int spider_mysql_handler::append_group_by_part( +int spider_mbase_handler::append_group_by_part( ORDER *order, const char *alias, uint alias_length, @@ -13516,7 +13779,7 @@ int spider_mysql_handler::append_group_by_part( ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_group_by_part"); + DBUG_ENTER("spider_mbase_handler::append_group_by_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -13531,7 +13794,7 @@ int spider_mysql_handler::append_group_by_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_group_by( +int spider_mbase_handler::append_group_by( ORDER *order, spider_string *str, const char *alias, @@ -13540,8 +13803,7 @@ int spider_mysql_handler::append_group_by( spider_fields *fields ) { int error_num; - uint dbton_id = spider_dbton_mysql.dbton_id; - DBUG_ENTER("spider_mysql_handler::append_group_by"); + DBUG_ENTER("spider_mbase_handler::append_group_by"); DBUG_PRINT("info",("spider this=%p", this)); if (order) { @@ -13564,7 +13826,7 @@ int spider_mysql_handler::append_group_by( DBUG_RETURN(0); } -int spider_mysql_handler::append_order_by_part( +int spider_mbase_handler::append_order_by_part( ORDER *order, const char *alias, uint alias_length, @@ -13574,7 +13836,7 @@ int spider_mysql_handler::append_order_by_part( ) { int error_num; spider_string *str; - DBUG_ENTER("spider_mysql_handler::append_order_by_part"); + DBUG_ENTER("spider_mbase_handler::append_order_by_part"); DBUG_PRINT("info",("spider this=%p", this)); switch (sql_type) { @@ -13589,7 +13851,7 @@ int spider_mysql_handler::append_order_by_part( DBUG_RETURN(error_num); } -int spider_mysql_handler::append_order_by( +int spider_mbase_handler::append_order_by( ORDER *order, spider_string *str, const char *alias, @@ -13598,8 +13860,7 @@ int spider_mysql_handler::append_order_by( spider_fields *fields ) { int error_num; - uint dbton_id = spider_dbton_mysql.dbton_id; - DBUG_ENTER("spider_mysql_handler::append_order_by"); + DBUG_ENTER("spider_mbase_handler::append_order_by"); DBUG_PRINT("info",("spider this=%p", this)); if (order) { @@ -13631,18 +13892,45 @@ int spider_mysql_handler::append_order_by( } #endif -spider_mysql_copy_table::spider_mysql_copy_table( - spider_mysql_share *db_share +spider_mbase_copy_table::spider_mbase_copy_table( + spider_mbase_share *db_share ) : spider_db_copy_table( db_share ), mysql_share(db_share) { + DBUG_ENTER("spider_mbase_copy_table::spider_mbase_copy_table"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_mysql_copy_table::spider_mysql_copy_table( + spider_mbase_share *db_share +) : spider_mbase_copy_table( + db_share +) { DBUG_ENTER("spider_mysql_copy_table::spider_mysql_copy_table"); DBUG_PRINT("info",("spider this=%p", this)); DBUG_VOID_RETURN; } +spider_mariadb_copy_table::spider_mariadb_copy_table( + spider_mbase_share *db_share +) : spider_mbase_copy_table( + db_share +) { + DBUG_ENTER("spider_mariadb_copy_table::spider_mariadb_copy_table"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +spider_mbase_copy_table::~spider_mbase_copy_table() +{ + DBUG_ENTER("spider_mbase_copy_table::~spider_mbase_copy_table"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + spider_mysql_copy_table::~spider_mysql_copy_table() { DBUG_ENTER("spider_mysql_copy_table::~spider_mysql_copy_table"); @@ -13650,26 +13938,33 @@ spider_mysql_copy_table::~spider_mysql_copy_table() DBUG_VOID_RETURN; } -int spider_mysql_copy_table::init() +spider_mariadb_copy_table::~spider_mariadb_copy_table() { - DBUG_ENTER("spider_mysql_copy_table::init"); + DBUG_ENTER("spider_mariadb_copy_table::~spider_mariadb_copy_table"); + DBUG_PRINT("info",("spider this=%p", this)); + DBUG_VOID_RETURN; +} + +int spider_mbase_copy_table::init() +{ + DBUG_ENTER("spider_mbase_copy_table::init"); DBUG_PRINT("info",("spider this=%p", this)); sql.init_calc_mem(78); DBUG_RETURN(0); } -void spider_mysql_copy_table::set_sql_charset( +void spider_mbase_copy_table::set_sql_charset( CHARSET_INFO *cs ) { - DBUG_ENTER("spider_mysql_copy_table::set_sql_charset"); + DBUG_ENTER("spider_mbase_copy_table::set_sql_charset"); DBUG_PRINT("info",("spider this=%p", this)); sql.set_charset(cs); DBUG_VOID_RETURN; } -int spider_mysql_copy_table::append_select_str() +int spider_mbase_copy_table::append_select_str() { - DBUG_ENTER("spider_mysql_copy_table::append_select_str"); + DBUG_ENTER("spider_mbase_copy_table::append_select_str"); DBUG_PRINT("info",("spider this=%p", this)); if (sql.reserve(SPIDER_SQL_SELECT_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -13677,10 +13972,10 @@ int spider_mysql_copy_table::append_select_str() DBUG_RETURN(0); } -int spider_mysql_copy_table::append_insert_str( +int spider_mbase_copy_table::append_insert_str( int insert_flg ) { - DBUG_ENTER("spider_mysql_copy_table::append_insert_str"); + DBUG_ENTER("spider_mbase_copy_table::append_insert_str"); DBUG_PRINT("info",("spider this=%p", this)); if (insert_flg & SPIDER_DB_INSERT_REPLACE) { @@ -13719,12 +14014,12 @@ int spider_mysql_copy_table::append_insert_str( DBUG_RETURN(0); } -int spider_mysql_copy_table::append_table_columns( +int spider_mbase_copy_table::append_table_columns( TABLE_SHARE *table_share ) { int error_num; Field **field; - DBUG_ENTER("spider_mysql_copy_table::append_table_columns"); + DBUG_ENTER("spider_mbase_copy_table::append_table_columns"); DBUG_PRINT("info",("spider this=%p", this)); for (field = table_share->field; *field; field++) { @@ -13732,7 +14027,7 @@ int spider_mysql_copy_table::append_table_columns( DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - (*field)->field_name, spider_dbton_mysql.dbton_id))) + (*field)->field_name, dbton_id))) DBUG_RETURN(error_num); if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN + SPIDER_SQL_COMMA_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -13743,9 +14038,9 @@ int spider_mysql_copy_table::append_table_columns( DBUG_RETURN(0); } -int spider_mysql_copy_table::append_from_str() +int spider_mbase_copy_table::append_from_str() { - DBUG_ENTER("spider_mysql_copy_table::append_from_str"); + DBUG_ENTER("spider_mbase_copy_table::append_from_str"); DBUG_PRINT("info",("spider this=%p", this)); if (sql.reserve(SPIDER_SQL_FROM_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -13753,40 +14048,40 @@ int spider_mysql_copy_table::append_from_str() DBUG_RETURN(0); } -int spider_mysql_copy_table::append_table_name( +int spider_mbase_copy_table::append_table_name( int link_idx ) { int error_num; - DBUG_ENTER("spider_mysql_copy_table::append_table_name"); + DBUG_ENTER("spider_mbase_copy_table::append_table_name"); DBUG_PRINT("info",("spider this=%p", this)); error_num = mysql_share->append_table_name(&sql, link_idx); DBUG_RETURN(error_num); } -void spider_mysql_copy_table::set_sql_pos() +void spider_mbase_copy_table::set_sql_pos() { - DBUG_ENTER("spider_mysql_copy_table::set_sql_pos"); + DBUG_ENTER("spider_mbase_copy_table::set_sql_pos"); DBUG_PRINT("info",("spider this=%p", this)); pos = sql.length(); DBUG_VOID_RETURN; } -void spider_mysql_copy_table::set_sql_to_pos() +void spider_mbase_copy_table::set_sql_to_pos() { - DBUG_ENTER("spider_mysql_copy_table::set_sql_to_pos"); + DBUG_ENTER("spider_mbase_copy_table::set_sql_to_pos"); DBUG_PRINT("info",("spider this=%p", this)); sql.length(pos); DBUG_VOID_RETURN; } -int spider_mysql_copy_table::append_copy_where( +int spider_mbase_copy_table::append_copy_where( spider_db_copy_table *source_ct, KEY *key_info, ulong *last_row_pos, ulong *last_lengths ) { int error_num, roop_count, roop_count2; - DBUG_ENTER("spider_mysql_copy_table::append_copy_where"); + DBUG_ENTER("spider_mbase_copy_table::append_copy_where"); DBUG_PRINT("info",("spider this=%p", this)); if (sql.reserve(SPIDER_SQL_WHERE_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) { @@ -13832,7 +14127,7 @@ int spider_mysql_copy_table::append_copy_where( DBUG_RETURN(0); } -int spider_mysql_copy_table::append_key_order_str( +int spider_mbase_copy_table::append_key_order_str( KEY *key_info, int start_pos, bool desc_flg @@ -13840,7 +14135,7 @@ int spider_mysql_copy_table::append_key_order_str( int length, error_num; KEY_PART_INFO *key_part; Field *field; - DBUG_ENTER("spider_mysql_copy_table::append_key_order_str"); + DBUG_ENTER("spider_mbase_copy_table::append_key_order_str"); DBUG_PRINT("info",("spider this=%p", this)); if ((int) spider_user_defined_key_parts(key_info) > start_pos) { @@ -13861,7 +14156,7 @@ int spider_mysql_copy_table::append_key_order_str( DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - field->field_name, spider_dbton_mysql.dbton_id))) + field->field_name, dbton_id))) DBUG_RETURN(error_num); if (key_part->key_part_flag & HA_REVERSE_SORT) { @@ -13891,7 +14186,7 @@ int spider_mysql_copy_table::append_key_order_str( DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - field->field_name, spider_dbton_mysql.dbton_id))) + field->field_name, dbton_id))) DBUG_RETURN(error_num); if (key_part->key_part_flag & HA_REVERSE_SORT) { @@ -13914,13 +14209,13 @@ int spider_mysql_copy_table::append_key_order_str( DBUG_RETURN(0); } -int spider_mysql_copy_table::append_limit( +int spider_mbase_copy_table::append_limit( longlong offset, longlong limit ) { char buf[SPIDER_LONGLONG_LEN + 1]; uint32 length; - DBUG_ENTER("spider_mysql_copy_table::append_limit"); + DBUG_ENTER("spider_mbase_copy_table::append_limit"); DBUG_PRINT("info",("spider this=%p", this)); if (offset || limit < 9223372036854775807LL) { @@ -13942,9 +14237,9 @@ int spider_mysql_copy_table::append_limit( DBUG_RETURN(0); } -int spider_mysql_copy_table::append_into_str() +int spider_mbase_copy_table::append_into_str() { - DBUG_ENTER("spider_mysql_copy_table::append_into_str"); + DBUG_ENTER("spider_mbase_copy_table::append_into_str"); DBUG_PRINT("info",("spider this=%p", this)); if (sql.reserve(SPIDER_SQL_INTO_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -13952,9 +14247,9 @@ int spider_mysql_copy_table::append_into_str() DBUG_RETURN(0); } -int spider_mysql_copy_table::append_open_paren_str() +int spider_mbase_copy_table::append_open_paren_str() { - DBUG_ENTER("spider_mysql_copy_table::append_open_paren_str"); + DBUG_ENTER("spider_mbase_copy_table::append_open_paren_str"); DBUG_PRINT("info",("spider this=%p", this)); if (sql.reserve(SPIDER_SQL_OPEN_PAREN_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -13962,9 +14257,9 @@ int spider_mysql_copy_table::append_open_paren_str() DBUG_RETURN(0); } -int spider_mysql_copy_table::append_values_str() +int spider_mbase_copy_table::append_values_str() { - DBUG_ENTER("spider_mysql_copy_table::append_values_str"); + DBUG_ENTER("spider_mbase_copy_table::append_values_str"); DBUG_PRINT("info",("spider this=%p", this)); if (sql.reserve(SPIDER_SQL_CLOSE_PAREN_LEN + SPIDER_SQL_VALUES_LEN + SPIDER_SQL_OPEN_PAREN_LEN)) @@ -13975,10 +14270,10 @@ int spider_mysql_copy_table::append_values_str() DBUG_RETURN(0); } -int spider_mysql_copy_table::append_select_lock_str( +int spider_mbase_copy_table::append_select_lock_str( int lock_mode ) { - DBUG_ENTER("spider_mysql_copy_table::append_select_lock_str"); + DBUG_ENTER("spider_mbase_copy_table::append_select_lock_str"); DBUG_PRINT("info",("spider this=%p", this)); if (lock_mode == SPIDER_LOCK_MODE_EXCLUSIVE) { @@ -13994,20 +14289,20 @@ int spider_mysql_copy_table::append_select_lock_str( DBUG_RETURN(0); } -int spider_mysql_copy_table::exec_query( +int spider_mbase_copy_table::exec_query( SPIDER_CONN *conn, int quick_mode, int *need_mon ) { int error_num; - DBUG_ENTER("spider_mysql_copy_table::exec_query"); + DBUG_ENTER("spider_mbase_copy_table::exec_query"); DBUG_PRINT("info",("spider this=%p", this)); error_num = spider_db_query(conn, sql.ptr(), sql.length(), quick_mode, need_mon); DBUG_RETURN(error_num); } -int spider_mysql_copy_table::copy_key_row( +int spider_mbase_copy_table::copy_key_row( spider_db_copy_table *source_ct, Field *field, ulong *row_pos, @@ -14016,14 +14311,14 @@ int spider_mysql_copy_table::copy_key_row( const int joint_length ) { int error_num; - spider_string *source_str = &((spider_mysql_copy_table *) source_ct)->sql; - DBUG_ENTER("spider_mysql_copy_table::copy_key_row"); + spider_string *source_str = &((spider_mbase_copy_table *) source_ct)->sql; + DBUG_ENTER("spider_mbase_copy_table::copy_key_row"); DBUG_PRINT("info",("spider this=%p", this)); if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); if ((error_num = spider_db_append_name_with_quote_str(&sql, - field->field_name, spider_dbton_mysql.dbton_id))) + field->field_name, dbton_id))) DBUG_RETURN(error_num); if (sql.reserve(SPIDER_SQL_NAME_QUOTE_LEN + joint_length + *length + SPIDER_SQL_AND_LEN)) @@ -14035,12 +14330,12 @@ int spider_mysql_copy_table::copy_key_row( DBUG_RETURN(0); } -int spider_mysql_copy_table::copy_row( +int spider_mbase_copy_table::copy_row( Field *field, SPIDER_DB_ROW *row ) { int error_num; - DBUG_ENTER("spider_mysql_copy_table::copy_row"); + DBUG_ENTER("spider_mbase_copy_table::copy_row"); DBUG_PRINT("info",("spider this=%p", this)); if (row->is_null()) { @@ -14053,7 +14348,7 @@ int spider_mysql_copy_table::copy_row( DBUG_RETURN(HA_ERR_OUT_OF_MEM); sql.q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); if ((error_num = row->append_escaped_to_str(&sql, - spider_dbton_mysql.dbton_id))) + dbton_id))) DBUG_RETURN(error_num); if (sql.reserve(SPIDER_SQL_VALUE_QUOTE_LEN + SPIDER_SQL_COMMA_LEN)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -14068,7 +14363,7 @@ int spider_mysql_copy_table::copy_row( DBUG_RETURN(0); } -int spider_mysql_copy_table::copy_rows( +int spider_mbase_copy_table::copy_rows( TABLE *table, SPIDER_DB_ROW *row, ulong **last_row_pos, @@ -14077,7 +14372,7 @@ int spider_mysql_copy_table::copy_rows( int error_num; Field **field; ulong *lengths2, *row_pos2; - DBUG_ENTER("spider_mysql_copy_table::copy_rows"); + DBUG_ENTER("spider_mbase_copy_table::copy_rows"); DBUG_PRINT("info",("spider this=%p", this)); row_pos2 = *last_row_pos; lengths2 = *last_lengths; @@ -14108,13 +14403,13 @@ int spider_mysql_copy_table::copy_rows( DBUG_RETURN(0); } -int spider_mysql_copy_table::copy_rows( +int spider_mbase_copy_table::copy_rows( TABLE *table, SPIDER_DB_ROW *row ) { int error_num; Field **field; - DBUG_ENTER("spider_mysql_copy_table::copy_rows"); + DBUG_ENTER("spider_mbase_copy_table::copy_rows"); DBUG_PRINT("info",("spider this=%p", this)); for ( field = table->field; @@ -14138,22 +14433,22 @@ int spider_mysql_copy_table::copy_rows( DBUG_RETURN(0); } -int spider_mysql_copy_table::append_insert_terminator() +int spider_mbase_copy_table::append_insert_terminator() { - DBUG_ENTER("spider_mysql_copy_table::append_insert_terminator"); + DBUG_ENTER("spider_mbase_copy_table::append_insert_terminator"); DBUG_PRINT("info",("spider this=%p", this)); sql.length(sql.length() - SPIDER_SQL_COMMA_LEN - SPIDER_SQL_OPEN_PAREN_LEN); DBUG_RETURN(0); } -int spider_mysql_copy_table::copy_insert_values( +int spider_mbase_copy_table::copy_insert_values( spider_db_copy_table *source_ct ) { - spider_mysql_copy_table *tmp_ct = (spider_mysql_copy_table *) source_ct; + spider_mbase_copy_table *tmp_ct = (spider_mbase_copy_table *) source_ct; spider_string *source_str = &tmp_ct->sql; int values_length = source_str->length() - tmp_ct->pos; const char *values_ptr = source_str->ptr() + tmp_ct->pos; - DBUG_ENTER("spider_mysql_copy_table::copy_insert_values"); + DBUG_ENTER("spider_mbase_copy_table::copy_insert_values"); DBUG_PRINT("info",("spider this=%p", this)); if (sql.reserve(values_length)) { diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index 9a709f46c51..3448cea06cc 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -13,11 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -class spider_db_mysql_util: public spider_db_util +class spider_db_mbase_util: public spider_db_util { public: - spider_db_mysql_util(); - ~spider_db_mysql_util(); + spider_db_mbase_util(); + virtual ~spider_db_mbase_util(); int append_name( spider_string *str, const char *name, @@ -174,7 +174,21 @@ public: #endif }; -class spider_db_mysql_row: public spider_db_row +class spider_db_mysql_util: public spider_db_mbase_util +{ +public: + spider_db_mysql_util(); + ~spider_db_mysql_util(); +}; + +class spider_db_mariadb_util: public spider_db_mbase_util +{ +public: + spider_db_mariadb_util(); + ~spider_db_mariadb_util(); +}; + +class spider_db_mbase_row: public spider_db_row { public: MYSQL_ROW row; @@ -184,8 +198,10 @@ public: uint field_count; uint record_size; bool cloned; - spider_db_mysql_row(); - ~spider_db_mysql_row(); + spider_db_mbase_row( + uint dbton_id + ); + virtual ~spider_db_mbase_row(); int store_to_field( Field *field, CHARSET_INFO *access_charset @@ -214,15 +230,31 @@ public: uint get_byte_size(); }; -class spider_db_mysql_result: public spider_db_result +class spider_db_mysql_row: public spider_db_mbase_row +{ +public: + spider_db_mysql_row(); + ~spider_db_mysql_row(); +}; + +class spider_db_mariadb_row: public spider_db_mbase_row +{ +public: + spider_db_mariadb_row(); + ~spider_db_mariadb_row(); +}; + +class spider_db_mbase_result: public spider_db_result { public: MYSQL_RES *db_result; - spider_db_mysql_row row; + spider_db_mbase_row row; MYSQL_ROW_OFFSET first_row; int store_error_num; - spider_db_mysql_result(SPIDER_DB_CONN *in_db_conn); - ~spider_db_mysql_result(); + spider_db_mbase_result( + SPIDER_DB_CONN *in_db_conn + ); + virtual ~spider_db_mbase_result(); bool has_result(); void free_result(); SPIDER_DB_ROW *current_row(); @@ -289,9 +321,29 @@ public: #endif }; -class spider_db_mysql: public spider_db_conn +class spider_db_mysql_result: public spider_db_mbase_result { - int stored_error; +public: + spider_db_mysql_result( + SPIDER_DB_CONN *in_db_conn + ); + ~spider_db_mysql_result(); +}; + +class spider_db_mariadb_result: public spider_db_mbase_result +{ +public: + spider_db_mariadb_result( + SPIDER_DB_CONN *in_db_conn + ); + ~spider_db_mariadb_result(); +}; + +class spider_db_mbase: public spider_db_conn +{ +protected: + int stored_error; + spider_db_mbase_util *spider_db_mbase_utility; public: MYSQL *db_conn; HASH lock_table_hash; @@ -306,10 +358,11 @@ public: const char *handler_open_array_func_name; const char *handler_open_array_file_name; ulong handler_open_array_line_no; - spider_db_mysql( - SPIDER_CONN *conn + spider_db_mbase( + SPIDER_CONN *conn, + spider_db_mbase_util *spider_db_mbase_utility ); - ~spider_db_mysql(); + virtual ~spider_db_mbase(); int init(); bool is_connected(); void bg_connect(); @@ -524,8 +577,28 @@ public: ); }; -class spider_mysql_share: public spider_db_share +class spider_db_mysql: public spider_db_mbase { +public: + spider_db_mysql( + SPIDER_CONN *conn + ); + ~spider_db_mysql(); +}; + +class spider_db_mariadb: public spider_db_mbase +{ +public: + spider_db_mariadb( + SPIDER_CONN *conn + ); + ~spider_db_mariadb(); +}; + +class spider_mbase_share: public spider_db_share +{ +protected: + spider_db_mbase_util *spider_db_mbase_utility; public: spider_string *table_select; int table_select_pos; @@ -547,10 +620,12 @@ public: bool same_db_table_name; int first_all_link_idx; - spider_mysql_share( - st_spider_share *share + spider_mbase_share( + st_spider_share *share, + uint dbton_id, + spider_db_mbase_util *spider_db_mbase_utility ); - ~spider_mysql_share(); + virtual ~spider_mbase_share(); int init(); uint get_column_name_length( uint field_index @@ -585,7 +660,7 @@ public: spider_string *str ); #endif -private: +protected: int create_table_names_str(); void free_table_names_str(); int create_column_name_str(); @@ -603,8 +678,28 @@ private: ); }; -class spider_mysql_handler: public spider_db_handler +class spider_mysql_share: public spider_mbase_share { +public: + spider_mysql_share( + st_spider_share *share + ); + ~spider_mysql_share(); +}; + +class spider_mariadb_share: public spider_mbase_share +{ +public: + spider_mariadb_share( + st_spider_share *share + ); + ~spider_mariadb_share(); +}; + +class spider_mbase_handler: public spider_db_handler +{ +protected: + spider_db_mbase_util *spider_db_mbase_utility; spider_string sql; spider_string sql_part; spider_string sql_part2; @@ -614,7 +709,7 @@ class spider_mysql_handler: public spider_db_handler int limit_pos; public: int table_name_pos; -private: +protected: int ha_read_pos; int ha_next_pos; int ha_where_pos; @@ -647,14 +742,15 @@ private: SPIDER_INT_HLD *union_table_name_pos_first; SPIDER_INT_HLD *union_table_name_pos_current; public: - spider_mysql_share *mysql_share; + spider_mbase_share *mysql_share; SPIDER_LINK_FOR_HASH *link_for_hash; uchar *minimum_select_bitmap; - spider_mysql_handler( + spider_mbase_handler( ha_spider *spider, - spider_mysql_share *share + spider_mbase_share *share, + spider_db_mbase_util *spider_db_mbase_utility ); - ~spider_mysql_handler(); + virtual ~spider_mbase_handler(); int init(); int append_index_hint( spider_string *str, @@ -1498,16 +1594,36 @@ public: #endif }; -class spider_mysql_copy_table: public spider_db_copy_table +class spider_mysql_handler: public spider_mbase_handler { public: - spider_mysql_share *mysql_share; + spider_mysql_handler( + ha_spider *spider, + spider_mbase_share *share + ); + ~spider_mysql_handler(); +}; + +class spider_mariadb_handler: public spider_mbase_handler +{ +public: + spider_mariadb_handler( + ha_spider *spider, + spider_mbase_share *share + ); + ~spider_mariadb_handler(); +}; + +class spider_mbase_copy_table: public spider_db_copy_table +{ +public: + spider_mbase_share *mysql_share; spider_string sql; uint pos; - spider_mysql_copy_table( - spider_mysql_share *db_share + spider_mbase_copy_table( + spider_mbase_share *db_share ); - ~spider_mysql_copy_table(); + virtual ~spider_mbase_copy_table(); int init(); void set_sql_charset( CHARSET_INFO *cs @@ -1578,3 +1694,21 @@ public: spider_db_copy_table *source_ct ); }; + +class spider_mysql_copy_table: public spider_mbase_copy_table +{ +public: + spider_mysql_copy_table( + spider_mbase_share *db_share + ); + ~spider_mysql_copy_table(); +}; + +class spider_mariadb_copy_table: public spider_mbase_copy_table +{ +public: + spider_mariadb_copy_table( + spider_mbase_share *db_share + ); + ~spider_mariadb_copy_table(); +}; diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc index 82a1e9a0fbc..eae749f6867 100644 --- a/storage/spider/spd_db_oracle.cc +++ b/storage/spider/spd_db_oracle.cc @@ -512,7 +512,7 @@ SPIDER_DB_ROW *spider_db_oracle_row::clone() spider_db_oracle_row *clone_row; DBUG_ENTER("spider_db_oracle_row::clone"); DBUG_PRINT("info",("spider this=%p", this)); - if (!(clone_row = new spider_db_oracle_row())) + if (!(clone_row = new spider_db_oracle_row(dbton_id))) { DBUG_RETURN(NULL); } @@ -772,9 +772,9 @@ int spider_db_oracle_row::fetch() } spider_db_oracle_result::spider_db_oracle_result(SPIDER_DB_CONN *in_db_conn) : - spider_db_result(in_db_conn, spider_dbton_oracle.dbton_id), + spider_db_result(in_db_conn), db_conn(NULL), stmtp(NULL), field_count(0), access_charset(NULL), - fetched(FALSE) + fetched(FALSE), row(in_db_conn->dbton_id) { DBUG_ENTER("spider_db_oracle_result::spider_db_oracle_result"); DBUG_PRINT("info",("spider this=%p", this)); @@ -4365,7 +4365,8 @@ int spider_db_oracle_util::append_having( spider_oracle_share::spider_oracle_share( st_spider_share *share ) : spider_db_share( - share + share, + spider_dbton_oracle.dbton_id ), table_select(NULL), table_select_pos(0), diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index fe5265184b6..0e706219432 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -128,6 +128,7 @@ extern long spider_conn_mutex_id; handlerton *spider_hton_ptr; SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE]; extern SPIDER_DBTON spider_dbton_mysql; +extern SPIDER_DBTON spider_dbton_mariadb; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) extern SPIDER_DBTON spider_dbton_handlersocket; #endif @@ -7362,15 +7363,22 @@ int spider_db_init( #endif spider_dbton_mysql.dbton_id = dbton_id; + spider_dbton_mysql.db_util->dbton_id = dbton_id; spider_dbton[dbton_id] = spider_dbton_mysql; ++dbton_id; + spider_dbton_mariadb.dbton_id = dbton_id; + spider_dbton_mariadb.db_util->dbton_id = dbton_id; + spider_dbton[dbton_id] = spider_dbton_mariadb; + ++dbton_id; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) spider_dbton_handlersocket.dbton_id = dbton_id; + spider_dbton_handlersocket.db_util->dbton_id = dbton_id; spider_dbton[dbton_id] = spider_dbton_handlersocket; ++dbton_id; #endif #ifdef HAVE_ORACLE_OCI spider_dbton_oracle.dbton_id = dbton_id; + spider_dbton_oracle.db_util->dbton_id = dbton_id; spider_dbton[dbton_id] = spider_dbton_oracle; ++dbton_id; #endif From 20e19f69750466ac2c9bbf82ef5ba396fc842a08 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 31 Jan 2019 22:08:45 +0100 Subject: [PATCH 17/91] MDEV-17479 Assertion `mysql_socket.fd != -1' failed in inline_mysql_socket_send on server shutdown Do not try to write ER_SHUTDOWN error message to socket, when it is forcefully closed by the shutdown. This will avoid the race condition (attempt to write to closed socket, if connection shuts down by itself). --- sql/mysqld.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 77736607e22..9240622cadf 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1791,7 +1791,7 @@ static void close_connections(void) */ THD* save_thd= current_thd; set_current_thd(tmp); - close_connection(tmp,ER_SERVER_SHUTDOWN); + close_connection(tmp); set_current_thd(save_thd); } #endif From f669cecbe30da820b93ebff0d3ed27d578627e47 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Thu, 31 Jan 2019 02:20:51 +0530 Subject: [PATCH 18/91] MDEV-18415 mariabackup.mdev-14447 test case fails with Table 'test.t' doesn't exist in engine - Added retry logic if validation of first page fails with checksum mismatch. --- extra/mariabackup/xtrabackup.cc | 15 +++++++++++---- .../suite/mariabackup/mdev-14447.result | 1 + mysql-test/suite/mariabackup/mdev-14447.test | 14 ++++++++++++-- storage/innobase/buf/buf0buf.cc | 10 ++++++++++ storage/innobase/include/fsp0file.h | 19 +++++++++++++++++++ 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 87f8822c38b..6ba5d950104 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -3092,7 +3092,16 @@ xb_load_single_table_tablespace( die("Can't open datafile %s", name); } - err = file->validate_first_page(&flush_lsn); + for (int i = 0; i < 10; i++) { + err = file->validate_first_page(&flush_lsn); + if (err != DB_CORRUPTION) { + break; + } + + my_sleep(1000); + } + + bool is_empty_file = file->exists() && file->is_empty_file(); if (err == DB_SUCCESS && file->space_id() != SRV_TMP_SPACE_ID) { os_offset_t node_size = os_file_get_size(file->handle()); @@ -3124,9 +3133,7 @@ xb_load_single_table_tablespace( delete file; - if (err != DB_SUCCESS && err != DB_CORRUPTION && xtrabackup_backup) { - /* allow corrupted first page for xtrabackup, it could be just - zero-filled page, which we restore from redo log later */ + if (err != DB_SUCCESS && xtrabackup_backup && !is_empty_file) { die("Failed to not validate first page of the file %s, error %d",name, (int)err); } } diff --git a/mysql-test/suite/mariabackup/mdev-14447.result b/mysql-test/suite/mariabackup/mdev-14447.result index 3bca7eb5701..6600c13ed74 100644 --- a/mysql-test/suite/mariabackup/mdev-14447.result +++ b/mysql-test/suite/mariabackup/mdev-14447.result @@ -7,6 +7,7 @@ COMMIT; SELECT count(*) FROM t; count(*) 100000 +FOUND 1 /Checksum mismatch in datafile/ in backup.log # Prepare full backup, apply incremental one # Restore and check results # shutdown server diff --git a/mysql-test/suite/mariabackup/mdev-14447.test b/mysql-test/suite/mariabackup/mdev-14447.test index 689b578f2ab..96d12368547 100644 --- a/mysql-test/suite/mariabackup/mdev-14447.test +++ b/mysql-test/suite/mariabackup/mdev-14447.test @@ -1,3 +1,4 @@ +--source include/have_debug.inc call mtr.add_suppression("InnoDB: New log files created"); let $basedir=$MYSQLTEST_VARDIR/tmp/backup; @@ -9,16 +10,26 @@ echo # Create full backup , modify table, then create incremental/differential b --disable_result_log exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir; --enable_result_log + BEGIN; INSERT INTO t select uuid(), uuid(), uuid(), uuid() from seq_1_to_100000; COMMIT; SELECT count(*) FROM t; -exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir; +let $backuplog=$MYSQLTEST_VARDIR/tmp/backup.log; + +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir --dbug=+d,page_intermittent_checksum_mismatch 2> $backuplog; + +--let SEARCH_RANGE = 10000000 +--let SEARCH_PATTERN=Checksum mismatch in datafile +--let SEARCH_FILE=$backuplog +--source include/search_pattern_in_file.inc +remove_file $backuplog; --disable_result_log echo # Prepare full backup, apply incremental one; exec $XTRABACKUP --prepare --verbose --apply-log-only --target-dir=$basedir; + exec $XTRABACKUP --prepare --verbose --apply-log-only --target-dir=$basedir --incremental-dir=$incremental_dir ; echo # Restore and check results; @@ -36,7 +47,6 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --copy-back --datadir= echo # restart server; --source include/start_mysqld.inc - --enable_result_log SELECT count(*) FROM t; DROP TABLE t; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 8dc2fd20dbe..e97a36efa56 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1103,6 +1103,16 @@ buf_page_is_corrupted( if (srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_CRC32) { + + DBUG_EXECUTE_IF( + "page_intermittent_checksum_mismatch", { + static int page_counter; + if (page_counter++ == 2) { + checksum_field2++; + } + }); + + crc32 = buf_page_check_crc32(read_buf, checksum_field2); crc32_inited = true; diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h index 9bc7b4bf9c9..0cb6ccaf86c 100644 --- a/storage/innobase/include/fsp0file.h +++ b/storage/innobase/include/fsp0file.h @@ -314,6 +314,25 @@ public: return(m_last_os_error); } + /** Check whether the file is empty. + @return true if file is empty */ + bool is_empty_file() const + { +#ifdef _WIN32 + os_offset_t offset = + (os_offset_t) m_file_info.nFileSizeLow + | ((os_offset_t) m_file_info.nFileSizeHigh << 32); + + return (offset == 0); +#else + return (m_file_info.st_size == 0); +#endif + } + + /** Check if the file exist. + @return true if file exists. */ + bool exists() const { return m_exists; } + /** Test if the filepath provided looks the same as this filepath by string comparison. If they are two different paths to the same file, same_as() will be used to show that after the files are opened. From a2641b26111116adabe1e1c06b768d8c3e06e129 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 29 Jan 2019 13:15:59 +0100 Subject: [PATCH 19/91] MDEV-18380 : adjust max_statement_time in mariabackup --- extra/mariabackup/backup_mysql.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index 8936b577a9e..a691cb664f1 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -152,7 +152,7 @@ xb_mysql_connect() return(NULL); } - xb_mysql_query(connection, "SET SESSION wait_timeout=2147483", + xb_mysql_query(connection, "SET SESSION wait_timeout=2147483, max_statement_time=0", false, true); return(connection); From 7c7161a1bd150e61f530933f096a8035932071af Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 28 Jan 2019 14:38:39 +0530 Subject: [PATCH 20/91] MDEV-18194 Incremental prepare tries to access page which is out of tablespace bounds Problem: ======= Mariabackup incremental prepare creates new tablespace when it encounter new tablespace. It sets the intial size as FIL_IBD_FILE_INITIAL_SIZE (4). But while applying redo log, it tries to access 5th page and then it leads to out of tablespace error. Fix: === While parsing the redo log record, track FSP_SIZE in recv_spaces for the respective space id. Assign the recv_size for the tablespace when it is loaded. Extend the tablespace depends on recv_size while applying the redo log record. --- .../incremental_ddl_before_backup.result | 32 ++++++++++++ .../incremental_ddl_before_backup.test | 50 +++++++++++++++++++ storage/innobase/fil/fil0fil.cc | 2 +- storage/innobase/log/log0recv.cc | 30 +++++++++-- 4 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/mariabackup/incremental_ddl_before_backup.result create mode 100644 mysql-test/suite/mariabackup/incremental_ddl_before_backup.test diff --git a/mysql-test/suite/mariabackup/incremental_ddl_before_backup.result b/mysql-test/suite/mariabackup/incremental_ddl_before_backup.result new file mode 100644 index 00000000000..a6273a20ff5 --- /dev/null +++ b/mysql-test/suite/mariabackup/incremental_ddl_before_backup.result @@ -0,0 +1,32 @@ +call mtr.add_suppression("InnoDB: New log files created"); +CREATE TABLE t1(i INT) ENGINE INNODB; +CREATE TABLE t2(i INT PRIMARY KEY) ENGINE INNODB; +CREATE TABLE t3(i INT) ENGINE INNODB; +# Create full backup , modify table, then create incremental/differential backup +create table t4(f1 int not null, f2 int not null)engine=innodb; +insert into t4 values(1, 2), (2, 2), (3, 3), (5, 5), (6, 6), (4, 4), (9, 9); +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +rename table t4 to t7; +select count(*) from t7; +count(*) +7168 +# XTRABACKUP INCREMENTAL +# XTRABACKUP PREPARE +# XTRABACKUP INCREMENTAL PREPARE +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +select count(*) from t7; +count(*) +7168 +drop table t1, t2, t7, t3; diff --git a/mysql-test/suite/mariabackup/incremental_ddl_before_backup.test b/mysql-test/suite/mariabackup/incremental_ddl_before_backup.test new file mode 100644 index 00000000000..2136771b97e --- /dev/null +++ b/mysql-test/suite/mariabackup/incremental_ddl_before_backup.test @@ -0,0 +1,50 @@ +--source include/have_debug.inc + +call mtr.add_suppression("InnoDB: New log files created"); + +let $basedir=$MYSQLTEST_VARDIR/tmp/backup; +let $incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1; + +CREATE TABLE t1(i INT) ENGINE INNODB; +CREATE TABLE t2(i INT PRIMARY KEY) ENGINE INNODB; +CREATE TABLE t3(i INT) ENGINE INNODB; + +echo # Create full backup , modify table, then create incremental/differential backup; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir; +--enable_result_log + +create table t4(f1 int not null, f2 int not null)engine=innodb; +insert into t4 values(1, 2), (2, 2), (3, 3), (5, 5), (6, 6), (4, 4), (9, 9); +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +insert into t4 select * from t4; +rename table t4 to t7; +select count(*) from t7; + +--echo # XTRABACKUP INCREMENTAL +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$incremental_dir --incremental-basedir=$basedir; + +--echo # XTRABACKUP PREPARE +exec $XTRABACKUP --apply-log-only --prepare --target-dir=$basedir; + +--echo # XTRABACKUP INCREMENTAL PREPARE +exec $XTRABACKUP --prepare --target-dir=$basedir --incremental-dir=$incremental_dir; + +let $targetdir=$basedir; +-- source include/restart_and_restore.inc +--enable_result_log + +select count(*) from t7; +drop table t1, t2, t7, t3; + +# Cleanup +rmdir $basedir; +rmdir $incremental_dir; diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 604f43d7639..623aa38be38 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -963,7 +963,7 @@ fil_space_extend_must_retry( we have set the node->being_extended flag. */ mutex_exit(&fil_system->mutex); - ut_ad(size > space->size); + ut_ad(size >= space->size); ulint last_page_no = space->size; const ulint file_start_page_no = last_page_no - node->size; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index f71067fddf2..bcd6254ebd6 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -152,9 +152,13 @@ struct file_name_t { /** Status of the tablespace */ fil_status status; + /** FSP_SIZE of tablespace */ + ulint size; + /** Constructor */ file_name_t(std::string name_, bool deleted) : - name(name_), space(NULL), status(deleted ? DELETED: NORMAL) {} + name(name_), space(NULL), status(deleted ? DELETED: NORMAL), + size(0) {} }; /** Map of dirty tablespaces during recovery */ @@ -326,6 +330,11 @@ fil_name_process( ut_ad(space != NULL); if (f.space == NULL || f.space == space) { + + if (f.size && f.space == NULL) { + fil_space_set_recv_size(space->id, f.size); + } + f.name = fname.name; f.space = space; f.status = file_name_t::NORMAL; @@ -2394,11 +2403,24 @@ recv_parse_log_rec( } if (*page_no == 0 && *type == MLOG_4BYTES + && apply && mach_read_from_2(old_ptr) == FSP_HEADER_OFFSET + FSP_SIZE) { old_ptr += 2; - fil_space_set_recv_size(*space, - mach_parse_compressed(&old_ptr, - end_ptr)); + + ulint size = mach_parse_compressed(&old_ptr, end_ptr); + + recv_spaces_t::iterator it = recv_spaces.find(*space); + + ut_ad(!recv_sys->mlog_checkpoint_lsn + || *space == TRX_SYS_SPACE + || srv_is_undo_tablespace(*space) + || it != recv_spaces.end()); + + if (it != recv_spaces.end() && !it->second.space) { + it->second.size = size; + } + + fil_space_set_recv_size(*space, size); } return(new_ptr - ptr); From 09cea8703f3ec4e4f9e23855a339c9e3d5e84d3b Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Fri, 1 Feb 2019 17:10:27 +0400 Subject: [PATCH 21/91] MDEV-17148 DROP DATABASE throw "Directory not empty" after changed lower_case_table_names. No need to lowercase table names on case-sensitive file systems, as the cache won't contain the 'lowercased' table anyway. And it prevents the UPPERCASE.frm from being deleted. --- mysql-test/r/lowercase_table.result | 4 ++++ mysql-test/t/lowercase_table.test | 12 ++++++++++++ sql/sql_db.cc | 8 ++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result index ac7d3e6bf7b..823ffa7696f 100644 --- a/mysql-test/r/lowercase_table.result +++ b/mysql-test/r/lowercase_table.result @@ -127,3 +127,7 @@ Database (mysql_TE%) mysql_test drop database mysql_TEST; End of 10.0 tests +create database db1; +create table t1 (a int); +drop database db1; +drop table t1; diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test index c339105aae4..e0dcb6c36dd 100644 --- a/mysql-test/t/lowercase_table.test +++ b/mysql-test/t/lowercase_table.test @@ -118,3 +118,15 @@ show databases like "mysql_TE%"; drop database mysql_TEST; --echo End of 10.0 tests + +# +# MDEV-17148 DROP DATABASE throw "Directory not empty" after changed lower_case_table_names. +# + +let $datadir=`select @@datadir`; +create database db1; +create table t1 (a int); +copy_file $datadir/test/t1.frm $datadir/db1/T1.frm; +drop database db1; +drop table t1; + diff --git a/sql/sql_db.cc b/sql/sql_db.cc index e94303f7e62..0e554e29380 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1107,8 +1107,12 @@ static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp, table_list->table_name_length= table->length; table_list->open_type= OT_BASE_ONLY; - /* To be able to correctly look up the table in the table cache. */ - if (lower_case_table_names) + /* + On the case-insensitive file systems table is opened + with the lowercased file name. So we should lowercase + as well to look up the cache properly. + */ + if (lower_case_file_system) table_list->table_name_length= my_casedn_str(files_charset_info, table_list->table_name); From 239b2dcf6ed4345141dd5fb4e5e4f5a28221ca19 Mon Sep 17 00:00:00 2001 From: mkaruza Date: Fri, 1 Feb 2019 15:52:02 +0100 Subject: [PATCH 22/91] Updated wsrep-lib to galera cache encryption implementation --- sql/wsrep_server_state.cc | 1 + wsrep-lib | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/wsrep_server_state.cc b/sql/wsrep_server_state.cc index 4571201b07d..7fe0e216f25 100644 --- a/sql/wsrep_server_state.cc +++ b/sql/wsrep_server_state.cc @@ -34,6 +34,7 @@ Wsrep_server_state::Wsrep_server_state(const std::string& name, : wsrep::server_state(m_mutex, m_cond, m_service, + NULL, name, incoming_address, address, diff --git a/wsrep-lib b/wsrep-lib index 136767ae044..e7d72ae7f6a 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit 136767ae044eac53e7f3d76909d176cde0dc27a8 +Subproject commit e7d72ae7f6a6995a21d743389426a963429a1fff From e214aa1cd35d282c27c1888bcd6cf943340c67ff Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Sat, 2 Feb 2019 10:02:03 +0100 Subject: [PATCH 23/91] MDEV-18281 COM_RESET_CONNECTION changes the connection encoding Store original charset during client authentication, and restore it for COM_RESET_CONNECTION --- client/mysqltest.cc | 9 ++++++++- mysql-test/main/reset_connection.result | 20 ++++++++++++++++++++ mysql-test/main/reset_connection.test | 15 +++++++++++++++ sql/sql_class.cc | 1 + sql/sql_class.h | 3 +++ sql/sql_connect.cc | 1 + sql/sql_parse.cc | 3 +++ 7 files changed, 51 insertions(+), 1 deletion(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 47e92eba7f8..0eb8c896ba5 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -5966,6 +5966,7 @@ void do_connect(struct st_command *command) int read_timeout= 0; int write_timeout= 0; int connect_timeout= 0; + char *csname=0; struct st_connection* con_slot; static DYNAMIC_STRING ds_connection_name; @@ -6077,6 +6078,11 @@ void do_connect(struct st_command *command) { connect_timeout= atoi(con_options + sizeof("connect_timeout=")-1); } + else if (strncasecmp(con_options, "CHARSET=", + sizeof("CHARSET=") - 1) == 0) + { + csname= strdup(con_options + sizeof("CHARSET=") - 1); + } else die("Illegal option to connect: %.*s", (int) (end - con_options), con_options); @@ -6114,7 +6120,7 @@ void do_connect(struct st_command *command) mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS); mysql_options(con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0); mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_NAME, - charset_info->csname); + csname?csname: charset_info->csname); if (opt_charsets_dir) mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_DIR, opt_charsets_dir); @@ -6225,6 +6231,7 @@ void do_connect(struct st_command *command) #ifdef HAVE_SMEM dynstr_free(&ds_shm); #endif + free(csname); DBUG_VOID_RETURN; } diff --git a/mysql-test/main/reset_connection.result b/mysql-test/main/reset_connection.result index 925195f704e..54f6ffdbd25 100644 --- a/mysql-test/main/reset_connection.result +++ b/mysql-test/main/reset_connection.result @@ -5,3 +5,23 @@ Com_select 10 SHOW local STATUS LIKE 'com_select'; Variable_name Value Com_select 0 +# Test if charset changes after reset (utf8) +connect utf8_conn,localhost,root,,,,,CHARSET=utf8; +connection utf8_conn; +SELECT IF(@@character_set_client='utf8','OK', 'FAIL') AS RESULT; +RESULT +OK +SELECT IF(@@character_set_client='utf8','OK', 'FAIL') AS RESULT; +RESULT +OK +disconnect utf8_conn; +# Test if charset changes after reset (latin1) +connect latin1_conn,localhost,root,,,,,CHARSET=latin1; +connection latin1_conn; +SELECT IF(@@character_set_client='latin1','OK', 'FAIL') AS RESULT; +RESULT +OK +SELECT IF(@@character_set_client='latin1','OK', 'FAIL') AS RESULT; +RESULT +OK +disconnect latin1_conn; diff --git a/mysql-test/main/reset_connection.test b/mysql-test/main/reset_connection.test index 49f41c32fc3..73c8280703c 100644 --- a/mysql-test/main/reset_connection.test +++ b/mysql-test/main/reset_connection.test @@ -23,3 +23,18 @@ SHOW local STATUS LIKE 'com_select'; SHOW local STATUS LIKE 'com_select'; +--echo # Test if charset changes after reset (utf8) +connect(utf8_conn,localhost,root,,,,,CHARSET=utf8); +connection utf8_conn; +SELECT IF(@@character_set_client='utf8','OK', 'FAIL') AS RESULT; +--reset_connection +SELECT IF(@@character_set_client='utf8','OK', 'FAIL') AS RESULT; +disconnect utf8_conn; + +--echo # Test if charset changes after reset (latin1) +connect(latin1_conn,localhost,root,,,,,CHARSET=latin1); +connection latin1_conn; +SELECT IF(@@character_set_client='latin1','OK', 'FAIL') AS RESULT; +--reset_connection +SELECT IF(@@character_set_client='latin1','OK', 'FAIL') AS RESULT; +disconnect latin1_conn; \ No newline at end of file diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 2efdf91f6a9..85c29b6b661 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -847,6 +847,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock) prepare_derived_at_open= FALSE; create_tmp_table_for_derived= FALSE; save_prep_leaf_list= FALSE; + org_charset= 0; /* Restore THR_THD */ set_current_thd(old_THR_THD); inc_thread_count(); diff --git a/sql/sql_class.h b/sql/sql_class.h index 1a7eb943193..b1fc89db7f2 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2365,6 +2365,9 @@ public: uint dbug_sentry; // watch out for memory corruption #endif struct st_my_thread_var *mysys_var; + + /* Original charset number from the first client packet, or COM_CHANGE_USER*/ + CHARSET_INFO *org_charset; private: /* Type of current query: COM_STMT_PREPARE, COM_QUERY, etc. Set from diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index b48070b9c8f..6881ca5956e 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -796,6 +796,7 @@ bool thd_init_client_charset(THD *thd, uint cs_number) cs->csname); return true; } + thd->org_charset= cs; thd->update_charset(cs,cs,cs); } return false; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 731dd3cba71..73f17c21abe 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1715,6 +1715,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->status_var.com_other++; thd->change_user(); thd->clear_error(); // if errors from rollback + /* Restore original charset from client authentication packet.*/ + if(thd->org_charset) + thd->update_charset(thd->org_charset,thd->org_charset,thd->org_charset); my_ok(thd, 0, 0, 0); break; } From 7293ce0ee81f05b1ec3ac9ddcc88bfbee4030e55 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Mon, 4 Feb 2019 17:52:39 +0300 Subject: [PATCH 24/91] MDEV-18470 improve alter_varchar_change.test Make ALGORITHM=INSTANT explicit. --- .../suite/innodb/r/alter_varchar_change.result | 18 +++++++++--------- .../suite/innodb/t/alter_varchar_change.test | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/mysql-test/suite/innodb/r/alter_varchar_change.result b/mysql-test/suite/innodb/r/alter_varchar_change.result index df7d49ca088..25adde6ffe4 100644 --- a/mysql-test/suite/innodb/r/alter_varchar_change.result +++ b/mysql-test/suite/innodb/r/alter_varchar_change.result @@ -15,7 +15,7 @@ SET @idx1_id = 0; CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); SELECT @tbl1_id = @tbl_id; @tbl1_id = @tbl_id @@ -32,7 +32,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), INDEX idx(f2))ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); SELECT @tbl1_id = @tbl_id; @tbl1_id = @tbl_id @@ -49,7 +49,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), f3 VARCHAR(100), INDEX idx(f2, f3), index idx1(f3, f2))ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); CALL get_index_id(@tbl_id, "idx", @idx_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200), MODIFY f3 VARCHAR(150); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), MODIFY f3 VARCHAR(150), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); CALL get_index_id(@tbl1_id, "idx", @idx1_id); SELECT @tbl1_id = @tbl_id; @@ -72,7 +72,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), INDEX idx(f2(40)))ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); CALL get_index_id(@tbl_id, "idx", @idx_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); CALL get_index_id(@tbl1_id, "idx", @idx1_id); SELECT @tbl1_id = @tbl_id; @@ -93,7 +93,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), FULLTEXT idx(f2))ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); CALL get_index_id(@tbl_id, "idx", @idx_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); CALL get_index_id(@tbl1_id, "idx", @idx1_id); SELECT @tbl1_id = @tbl_id; @@ -117,7 +117,7 @@ INDEX idx(f3))ENGINE=InnoDB; INSERT INTO t1(f1, f2) VALUES(1, repeat('a', 40)); CALL get_table_id("test/t1", @tbl_id); CALL get_index_id(@tbl_id, "idx", @idx_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(100); +ALTER TABLE t1 MODIFY f2 VARCHAR(100), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); CALL get_index_id(@tbl1_id, "idx", @idx1_id); SELECT @tbl1_id = @tbl_id; @@ -163,7 +163,7 @@ f2 VARCHAR(100), INDEX idx(f2(10)))ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); CALL get_index_id(@tbl_id, "idx", @idx_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(10)); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(10)), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); CALL get_index_id(@tbl1_id, "idx", @idx1_id); SELECT @tbl1_id = @tbl_id; @@ -251,7 +251,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), INDEX idx(f2))ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT; +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT, ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); SELECT @tbl1_id = @tbl_id; @tbl1_id = @tbl_id @@ -267,7 +267,7 @@ t1 CREATE TABLE `t1` ( DROP TABLE t1; CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT; +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT, ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); SELECT @tbl1_id = @tbl_id; @tbl1_id = @tbl_id diff --git a/mysql-test/suite/innodb/t/alter_varchar_change.test b/mysql-test/suite/innodb/t/alter_varchar_change.test index f435125e581..7e0c99487b5 100644 --- a/mysql-test/suite/innodb/t/alter_varchar_change.test +++ b/mysql-test/suite/innodb/t/alter_varchar_change.test @@ -26,7 +26,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); SELECT @tbl1_id = @tbl_id; @@ -39,7 +39,7 @@ CREATE TABLE t1(f1 INT NOT NULL, INDEX idx(f2))ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); SELECT @tbl1_id = @tbl_id; @@ -51,7 +51,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), f3 VARCHAR(100), CALL get_table_id("test/t1", @tbl_id); CALL get_index_id(@tbl_id, "idx", @idx_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200), MODIFY f3 VARCHAR(150); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), MODIFY f3 VARCHAR(150), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); CALL get_index_id(@tbl1_id, "idx", @idx1_id); @@ -65,7 +65,7 @@ CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), CALL get_table_id("test/t1", @tbl_id); CALL get_index_id(@tbl_id, "idx", @idx_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); CALL get_index_id(@tbl1_id, "idx", @idx1_id); @@ -80,7 +80,7 @@ CREATE TABLE t1(f1 INT NOT NULL, CALL get_table_id("test/t1", @tbl_id); CALL get_index_id(@tbl_id, "idx", @idx_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); CALL get_index_id(@tbl1_id, "idx", @idx1_id); @@ -98,7 +98,7 @@ INSERT INTO t1(f1, f2) VALUES(1, repeat('a', 40)); CALL get_table_id("test/t1", @tbl_id); CALL get_index_id(@tbl_id, "idx", @idx_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(100); +ALTER TABLE t1 MODIFY f2 VARCHAR(100), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); CALL get_index_id(@tbl1_id, "idx", @idx1_id); @@ -129,7 +129,7 @@ CREATE TABLE t1(f1 INT NOT NULL, CALL get_table_id("test/t1", @tbl_id); CALL get_index_id(@tbl_id, "idx", @idx_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(10)); +ALTER TABLE t1 MODIFY f2 VARCHAR(200), DROP INDEX idx, ADD INDEX idx(f2(10)), ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); CALL get_index_id(@tbl1_id, "idx", @idx1_id); @@ -192,7 +192,7 @@ CREATE TABLE t1(f1 INT NOT NULL, INDEX idx(f2))ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT; +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT, ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); SELECT @tbl1_id = @tbl_id; @@ -202,7 +202,7 @@ DROP TABLE t1; CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100) PRIMARY KEY)ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); -ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT; +ALTER TABLE t1 MODIFY f2 VARCHAR(200), ADD COLUMN f3 INT, ALGORITHM=INSTANT; CALL get_table_id("test/t1", @tbl1_id); SELECT @tbl1_id = @tbl_id; From eeaaf4a845268fe13c05a0cef4e79722d5835958 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 17 Jan 2019 13:07:26 +0100 Subject: [PATCH 25/91] stricter json unit tests --- unittest/strings/json-t.c | 123 ++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 51 deletions(-) diff --git a/unittest/strings/json-t.c b/unittest/strings/json-t.c index ce0f04dc030..7c5f7957d42 100644 --- a/unittest/strings/json-t.c +++ b/unittest/strings/json-t.c @@ -17,66 +17,87 @@ #include #include -int json_locate_key(const char *js, const char *js_end, const char *kname, - const char **key_start, const char **key_end, - int *comma_pos); -int main() +const char *json="{\"int\":1,\"str\":\"foo bar\"," + "\"array\":[10,20,{\"c\":\"d\"}],\"bool\":false}"; + +const char *json_ar="[1,\"foo bar\",[10,20,{\"c\":\"d\"}],false]"; + +const char *json_w="{\"int\" : 1 , " + "\"array\" : [10,20,{\"c\":\"d\"}] , \"bool\" : false }"; +const char *json_1="{ \"str\" : \"foo bar\" }"; + +void do_json(const char *key, int type, const char *value) { - const char *json="{\"int\":1, \"str\":\"foo bar\", " - "\"array\":[10,20,{\"c\":\"d\"}],\"bool\":false}"; - const char *json_ar="[1, \"foo bar\", " "[10,20,{\"c\":\"d\"}], false]"; - const char *json_w="{\"int\" : 1 , \"str\" : \"foo bar\" , " - "\"array\" : [10,20,{\"c\":\"d\"}] , \"bool\" : false }"; - const char *json_1="{ \"str\" : \"foo bar\" }"; enum json_types value_type; const char *value_start; int value_len; + + value_type= json_get_object_key(json, json + strlen(json), + key, &value_start, &value_len); + if (type) + ok(value_type == type && value_len == (int)strlen(value) && !memcmp(value_start, value, value_len), + "%s: type=%u, value(%d)=\"%.*s\"", key, value_type, value_len, value_len, value_start); + else + ok(value_type == type && value_len == (int)strlen(value), + "%s: type=%u keys=%u end=\"%s\"", key, value_type, value_len, value_start); +} + +void do_json_ar(int n, int type, const char *value) +{ + enum json_types value_type; + const char *value_start; + int value_len; + + value_type= json_get_array_item(json_ar, json_ar + strlen(json_ar), + n, &value_start, &value_len); + if (type) + ok(value_type == type && value_len == (int)strlen(value) && !memcmp(value_start, value, value_len), + "%i: type=%u, value(%d)=\"%.*s\"", n, value_type, value_len, value_len, value_start); + else + ok(value_type == type && value_len == (int)strlen(value), + "%i: type=%u keys=%u end=\"%s\"", n, value_type, value_len, value_start); +} + +void do_json_locate(const char *json, const char *key, int from, int to, int cp) +{ const char *key_start, *key_end; - int result, comma_pos; + int res, comma_pos; - plan(15); + res= json_locate_key(json, json + strlen(json), + key, &key_start, &key_end, &comma_pos); + if (key_start) + ok(res == 0 && key_start - json == from && key_end - json == to && + comma_pos == cp, "%s: [%d,%d,%d] %.*s%s", key, (int)(key_start-json), + (int)(key_end-json), comma_pos, (int)(key_start - json), json, key_end); + else + ok(res == 0 && from == -1, "%s: key not found", key); +} -#define do_json(V) \ - do { \ - value_type= json_get_object_key(json, json+strlen(json), \ - V, &value_start, &value_len); \ - ok(value_type != JSV_BAD_JSON, V); \ - diag("type=%d, value=\"%.*s\"", value_type, (int)value_len, value_start); \ - } while(0) -#define do_json_ar(N) \ - do { \ - value_type= json_get_array_item(json_ar, json_ar+strlen(json_ar), \ - N, &value_start, &value_len); \ - ok(value_type != JSV_BAD_JSON, #N); \ - diag("type=%d, value=\"%.*s\"", value_type, (int)value_len, value_start); \ - } while(0) -#define do_json_locate(J, V) \ - do { \ - result= json_locate_key(J, J+strlen(J), \ - V, &key_start, &key_end, &comma_pos); \ - ok(result == 0, V); \ - if (key_start) \ - diag("key_str=\"%.*s\" comma_pos= %d", (int)(key_end - key_start), key_start, comma_pos); \ - else \ - diag("no key found"); \ - } while(0) +int main() +{ + plan(18); - do_json("int"); - do_json("str"); - do_json("bool"); - do_json("c"); - do_json("array"); + diag("%s", json); + do_json("int", 4, "1"); + do_json("str", 3, "foo bar"); + do_json("bool", 6, "false"); + do_json("c", 0, "1234"); + do_json("array", 2, "[10,20,{\"c\":\"d\"}]"); + diag("%s", json_ar); + do_json_ar(0, 4, "1"); + do_json_ar(1, 3, "foo bar"); + do_json_ar(2, 2, "[10,20,{\"c\":\"d\"}]"); + do_json_ar(3, 6, "false"); + do_json_ar(4, 0, "1234"); - do_json_ar(0); - do_json_ar(1); - do_json_ar(2); - do_json_ar(3); - do_json_ar(4); + do_json_locate(json, "bool", 50, 63, 1); + do_json_locate(json, "int", 1, 9, 2); + do_json_locate(json, "array", 24, 50, 1); + do_json_locate(json_w, "bool", 43, 61, 1); + do_json_locate(json_w, "int", 1, 12, 2); + do_json_locate(json_w, "array", 11, 43, 1); + do_json_locate(json_w, "c", -1, -1, -1); + do_json_locate(json_1, "str", 1, 22, 0); - do_json_locate(json_w, "bool"); - do_json_locate(json_w, "int"); - do_json_locate(json_w, "array"); - do_json_locate(json_1, "str"); - do_json_locate(json_w, "c"); return exit_status(); } From 3ab445819e622fb5e09baf2153db26d10f2c8a29 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 9 Jan 2019 20:24:34 +0100 Subject: [PATCH 26/91] MDEV-18119 upgrading from 10.3 to 10.4 can result in the password for a user to be wiped ou --- mysql-test/main/mysql_upgrade.result | 41 +++++++++++++++++++++++++--- mysql-test/main/mysql_upgrade.test | 35 ++++++++++++++++++++---- scripts/mysql_system_tables_fix.sql | 2 +- 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/mysql-test/main/mysql_upgrade.result b/mysql-test/main/mysql_upgrade.result index a99895f53d7..9fcf76d2b1c 100644 --- a/mysql-test/main/mysql_upgrade.result +++ b/mysql-test/main/mysql_upgrade.result @@ -316,7 +316,7 @@ Grants for user3@% GRANT USAGE ON *.* TO 'user3'@'%' GRANT ALL PRIVILEGES ON `roelt`.`test2` TO 'user3'@'%' DROP USER 'user3'@'%'; -End of 5.1 tests +# End of 5.1 tests The --upgrade-system-tables option was used, user tables won't be touched. Phase 1/7: Checking and upgrading mysql database Processing databases @@ -505,7 +505,7 @@ length(table_name) 79 79 drop table extralongname_extralongname_extralongname_extralongname_ext; -End of 10.0 tests +# End of 10.0 tests set sql_mode=default; # Droping the previously created mysql_upgrade_info file.. create table test.t1(a int) engine=MyISAM; @@ -569,8 +569,8 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE test.t1; SET GLOBAL enforce_storage_engine=NULL; -End of 10.1 tests -Start of 10.3 tests +# End of 10.1 tests +# End of 10.2 tests # # Ensure that mysql_upgrade correctly sets truncate_versioning_priv # on upgrade from 10.2 @@ -591,3 +591,36 @@ DROP USER 'user3'@'%'; update mysql.db set Delete_history_priv='Y' where db like 'test%'; drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; +# End of 10.3 tests +drop view mysql.user_bak; +create user 'user3'@'localhost' identified with mysql_native_password as password('a_password'); +show create user user3@localhost; +CREATE USER for user3@localhost +CREATE USER 'user3'@'localhost' IDENTIFIED BY PASSWORD '*5DC1D11F45824A9DD613961F05C1EC1E7A1601AA' +update mysql.user set password=authentication_string, authentication_string='' where user='user3'; +select password,plugin,authentication_string from mysql.user where user='user3'; +password plugin authentication_string +*5DC1D11F45824A9DD613961F05C1EC1E7A1601AA mysql_native_password +flush privileges; +show create user user3@localhost; +CREATE USER for user3@localhost +CREATE USER 'user3'@'localhost' IDENTIFIED BY PASSWORD '*5DC1D11F45824A9DD613961F05C1EC1E7A1601AA' +connect con1,localhost,user3,a_password; +select current_user(); +current_user() +user3@localhost +disconnect con1; +connection default; +# mysql_upgrade --force --silent 2>&1 +show create user user3@localhost; +CREATE USER for user3@localhost +CREATE USER 'user3'@'localhost' IDENTIFIED BY PASSWORD '*5DC1D11F45824A9DD613961F05C1EC1E7A1601AA' +connect con1,localhost,user3,a_password; +select current_user(); +current_user() +user3@localhost +disconnect con1; +connection default; +drop user user3@localhost; +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; diff --git a/mysql-test/main/mysql_upgrade.test b/mysql-test/main/mysql_upgrade.test index d4a3d864c21..9ed39aa5d32 100644 --- a/mysql-test/main/mysql_upgrade.test +++ b/mysql-test/main/mysql_upgrade.test @@ -106,8 +106,7 @@ SHOW GRANTS FOR 'user3'@'%'; DROP USER 'user3'@'%'; ---echo End of 5.1 tests - +--echo # End of 5.1 tests # # Test the --upgrade-system-tables option @@ -192,7 +191,7 @@ create table extralongname_extralongname_extralongname_extralongname_ext ( select length(table_name) from mysql.innodb_table_stats; drop table extralongname_extralongname_extralongname_extralongname_ext; ---echo End of 10.0 tests +--echo # End of 10.0 tests set sql_mode=default; @@ -218,9 +217,9 @@ DROP TABLE test.t1; --remove_file $MYSQLD_DATADIR/mysql_upgrade_info SET GLOBAL enforce_storage_engine=NULL; ---echo End of 10.1 tests +--echo # End of 10.1 tests ---echo Start of 10.3 tests +--echo # End of 10.2 tests --echo # --echo # Ensure that mysql_upgrade correctly sets truncate_versioning_priv @@ -244,3 +243,29 @@ DROP USER 'user3'@'%'; update mysql.db set Delete_history_priv='Y' where db like 'test%'; drop table mysql.global_priv; rename table mysql.global_priv_bak to mysql.global_priv; + +--echo # End of 10.3 tests + +--source include/switch_to_mysql_user.inc +drop view mysql.user_bak; +create user 'user3'@'localhost' identified with mysql_native_password as password('a_password'); +show create user user3@localhost; +update mysql.user set password=authentication_string, authentication_string='' where user='user3'; +select password,plugin,authentication_string from mysql.user where user='user3'; +flush privileges; +show create user user3@localhost; +connect con1,localhost,user3,a_password; +select current_user(); +disconnect con1; +connection default; +--echo # mysql_upgrade --force --silent 2>&1 +--exec $MYSQL_UPGRADE --force --silent 2>&1 +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info +show create user user3@localhost; +connect con1,localhost,user3,a_password; +select current_user(); +disconnect con1; +connection default; +drop user user3@localhost; +drop table mysql.global_priv; +rename table mysql.global_priv_bak to mysql.global_priv; diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 82ec2faa12d..e80569d6636 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -803,7 +803,7 @@ IF 'BASE TABLE' = (select table_type from information_schema.tables where table_ 'max_user_connections', max_user_connections, 'max_statement_time', max_statement_time, 'plugin', if(plugin>'',plugin,if(length(password)=16,'mysql_old_password','mysql_native_password')), - 'authentication_string', if(plugin>'',authentication_string,password), + 'authentication_string', if(plugin>'' and authentication_string>'',authentication_string,password), 'default_role', default_role, 'is_role', 'Y'=is_role)) as Priv FROM user; From 3742f6f9aadc363fb83e3775066c33ba420fe97b Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 12 Jan 2019 21:36:26 +0100 Subject: [PATCH 27/91] cleanup: use only one callback in PAM plugin, not two --- plugin/auth_pam/auth_pam_base.c | 9 ++------- plugin/auth_pam/auth_pam_tool.c | 14 ++++---------- plugin/auth_pam/auth_pam_v1.c | 11 ++++------- 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/plugin/auth_pam/auth_pam_base.c b/plugin/auth_pam/auth_pam_base.c index 68be0e92b71..67a0adbeb2e 100644 --- a/plugin/auth_pam/auth_pam_base.c +++ b/plugin/auth_pam/auth_pam_base.c @@ -109,15 +109,10 @@ static int conv(int n, const struct pam_message **msg, param->buf[0] = msg[i]->msg_style == PAM_PROMPT_ECHO_ON ? 2 : 4; PAM_DEBUG((stderr, "PAM: conv: send(%.*s)\n", (int)(param->ptr - param->buf - 1), param->buf)); - if (write_packet(param, param->buf, param->ptr - param->buf - 1)) + pkt_len= roundtrip(param, param->buf, param->ptr - param->buf - 1, &pkt); + if (pkt_len < 0) return PAM_CONV_ERR; - pkt_len = read_packet(param, &pkt); - if (pkt_len < 0) - { - PAM_DEBUG((stderr, "PAM: conv: recv() ERROR\n")); - return PAM_CONV_ERR; - } PAM_DEBUG((stderr, "PAM: conv: recv(%.*s)\n", pkt_len, pkt)); /* allocate and copy the reply to the response array */ if (!((*resp)[i].resp= strndup((char*) pkt, pkt_len))) diff --git a/plugin/auth_pam/auth_pam_tool.c b/plugin/auth_pam/auth_pam_tool.c index 3f7015952a0..95d47dca113 100644 --- a/plugin/auth_pam/auth_pam_tool.c +++ b/plugin/auth_pam/auth_pam_tool.c @@ -26,22 +26,16 @@ struct param { #include "auth_pam_tool.h" -static int write_packet(struct param *param __attribute__((unused)), - const unsigned char *buf, int buf_len) +static int roundtrip(struct param *param, const unsigned char *buf, + int buf_len, unsigned char **pkt) { unsigned char b= AP_CONV; - return write(1, &b, 1) < 1 || - write_string(1, buf, buf_len); -} - - -static int read_packet(struct param *param, unsigned char **pkt) -{ + if (write(1, &b, 1) < 1 || write_string(1, buf, buf_len)) + return -1; *pkt= (unsigned char *) param->buf; return read_string(0, (char *) param->buf, (int) sizeof(param->buf)) - 1; } - typedef struct st_mysql_server_auth_info { /** diff --git a/plugin/auth_pam/auth_pam_v1.c b/plugin/auth_pam/auth_pam_v1.c index ab352b1492b..95110a5e310 100644 --- a/plugin/auth_pam/auth_pam_v1.c +++ b/plugin/auth_pam/auth_pam_v1.c @@ -21,14 +21,11 @@ struct param { MYSQL_PLUGIN_VIO *vio; }; -static int write_packet(struct param *param, const unsigned char *buf, - int buf_len) -{ - return param->vio->write_packet(param->vio, buf, buf_len); -} - -static int read_packet(struct param *param, unsigned char **pkt) +static int roundtrip(struct param *param, const unsigned char *buf, + int buf_len, unsigned char **pkt) { + if (param->vio->write_packet(param->vio, buf, buf_len)) + return -1; return param->vio->read_packet(param->vio, pkt); } From c94ec9fc6721f50fadb1d86d1d0bf004b39c69d2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 12 Jan 2019 15:56:25 +0100 Subject: [PATCH 28/91] MDEV-17950 SHOW GRANTS FOR does not work for a user identified with non-existing plugin Revert the side effect of 7c40996cc866. Do not convert password hash to its binary representation when a user entry is loaded. Do it lazily on the first authenticatation attempt. As a collateral - force all authentication plugins to follow the protocol and read_packet at least once before accessing info->username (username is not available before first client handshake packet is read). Fix PAM and GSSAPI plugins to behave. --- mysql-test/main/failed_auth_unixsocket.result | 9 +- mysql-test/main/failed_auth_unixsocket.test | 4 +- mysql-test/main/grant5.result | 22 +-- mysql-test/main/grant5.test | 8 - mysql-test/main/plugin_auth_qa_1.result | 4 +- mysql-test/main/plugin_auth_qa_1.test | 2 +- plugin/auth_gssapi/gssapi_server.cc | 20 ++- plugin/auth_gssapi/server_plugin.cc | 32 +--- plugin/auth_gssapi/server_plugin.h | 2 +- plugin/auth_gssapi/sspi_server.cc | 17 +- plugin/auth_pam/auth_pam.c | 32 ++-- plugin/auth_pam/auth_pam_v1.c | 20 ++- sql/sql_acl.cc | 159 ++++++++++-------- 13 files changed, 186 insertions(+), 145 deletions(-) diff --git a/mysql-test/main/failed_auth_unixsocket.result b/mysql-test/main/failed_auth_unixsocket.result index b2081c9ba84..690476cd753 100644 --- a/mysql-test/main/failed_auth_unixsocket.result +++ b/mysql-test/main/failed_auth_unixsocket.result @@ -1,13 +1,8 @@ update mysql.global_priv set priv=json_insert(priv, '$.plugin', 'unix_socket'); flush privileges; -Warnings: -Warning 1524 Plugin 'unix_socket' is not loaded -Warning 1524 Plugin 'unix_socket' is not loaded -Warning 1524 Plugin 'unix_socket' is not loaded -Warning 1524 Plugin 'unix_socket' is not loaded connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); -ERROR 28000: Access denied for user 'USER'@'localhost' (using password: NO) -ERROR 28000: Access denied for user 'USER'@'localhost' (using password: NO) +ERROR HY000: Plugin 'unix_socket' is not loaded +ERROR HY000: Plugin 'unix_socket' is not loaded install plugin unix_socket soname 'auth_socket.so'; flush privileges; connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); diff --git a/mysql-test/main/failed_auth_unixsocket.test b/mysql-test/main/failed_auth_unixsocket.test index 179e561e9ed..a7ae7d64a6b 100644 --- a/mysql-test/main/failed_auth_unixsocket.test +++ b/mysql-test/main/failed_auth_unixsocket.test @@ -14,12 +14,12 @@ let $replace=Access denied for user '$USER'; --echo connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); --replace_result $replace "Access denied for user 'USER'" --disable_query_log ---error ER_ACCESS_DENIED_ERROR +--error ER_PLUGIN_IS_NOT_LOADED connect (fail,localhost,$USER); --enable_query_log --replace_result $replace "Access denied for user 'USER'" ---error ER_ACCESS_DENIED_ERROR +--error ER_PLUGIN_IS_NOT_LOADED change_user $USER; eval install plugin unix_socket soname '$AUTH_SOCKET_SO'; diff --git a/mysql-test/main/grant5.result b/mysql-test/main/grant5.result index 5bf7b2d1934..c35e8201582 100644 --- a/mysql-test/main/grant5.result +++ b/mysql-test/main/grant5.result @@ -59,12 +59,9 @@ update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad') where user='u5'; update mysql.global_priv set priv=json_set(priv, '$.plugin', 'nonexistent') where user='u8'; flush privileges; -Warnings: -Error 1372 Password hash should be a 41-digit hexadecimal number -Error 1372 Password hash should be a 16-digit hexadecimal number -Warning 1524 Plugin 'nonexistent' is not loaded show create user u1@h; -ERROR 28000: Can't find any matching row in the user table +CREATE USER for u1@h +CREATE USER 'u1'@'h' IDENTIFIED BY PASSWORD 'bad' show create user u2@h; CREATE USER for u2@h CREATE USER 'u2'@'h' IDENTIFIED BY PASSWORD '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD' @@ -75,7 +72,8 @@ show create user u4@h; CREATE USER for u4@h CREATE USER 'u4'@'h' IDENTIFIED BY PASSWORD '*975B2CD4FF9AE554FE8AD33168FBFC326D2021DD' show create user u5@h; -ERROR 28000: Can't find any matching row in the user table +CREATE USER for u5@h +CREATE USER 'u5'@'h' IDENTIFIED BY PASSWORD 'bad' show create user u6@h; CREATE USER for u6@h CREATE USER 'u6'@'h' IDENTIFIED BY PASSWORD '78a302dd267f6044' @@ -83,26 +81,24 @@ show create user u7@h; CREATE USER for u7@h CREATE USER 'u7'@'h' IDENTIFIED BY PASSWORD '78a302dd267f6044' show create user u8@h; -ERROR 28000: Can't find any matching row in the user table +CREATE USER for u8@h +CREATE USER 'u8'@'h' IDENTIFIED VIA nonexistent USING '78a302dd267f6044' grant select on *.* to u1@h; -ERROR 28000: Can't find any matching row in the user table grant select on *.* to u2@h; grant select on *.* to u3@h; grant select on *.* to u4@h; grant select on *.* to u5@h; -ERROR 28000: Can't find any matching row in the user table grant select on *.* to u6@h; grant select on *.* to u7@h; grant select on *.* to u8@h; -ERROR 28000: Can't find any matching row in the user table select user,select_priv,plugin,authentication_string from mysql.user where user like 'u_'; User Select_priv plugin authentication_string -u1 N mysql_native_password bad +u1 Y mysql_native_password bad u2 Y mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD u3 Y mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD u4 Y mysql_native_password *975B2CD4FF9AE554FE8AD33168FBFC326D2021DD -u5 N mysql_old_password bad +u5 Y mysql_old_password bad u6 Y mysql_old_password 78a302dd267f6044 u7 Y mysql_old_password 78a302dd267f6044 -u8 N nonexistent 78a302dd267f6044 +u8 Y nonexistent 78a302dd267f6044 drop user u1@h, u2@h, u3@h, u4@h, u5@h, u6@h, u7@h, u8@h; diff --git a/mysql-test/main/grant5.test b/mysql-test/main/grant5.test index daf972dbe4b..cc673754461 100644 --- a/mysql-test/main/grant5.test +++ b/mysql-test/main/grant5.test @@ -66,29 +66,21 @@ update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad update mysql.global_priv set priv=json_set(priv, '$.authentication_string', 'bad') where user='u5'; update mysql.global_priv set priv=json_set(priv, '$.plugin', 'nonexistent') where user='u8'; flush privileges; -# invalid entries are skipped, users don't exist -error ER_PASSWORD_NO_MATCH; show create user u1@h; show create user u2@h; show create user u3@h; show create user u4@h; -error ER_PASSWORD_NO_MATCH; show create user u5@h; show create user u6@h; show create user u7@h; -error ER_PASSWORD_NO_MATCH; show create user u8@h; -#grants don't work either -error ER_PASSWORD_NO_MATCH; grant select on *.* to u1@h; grant select on *.* to u2@h; grant select on *.* to u3@h; grant select on *.* to u4@h; -error ER_PASSWORD_NO_MATCH; grant select on *.* to u5@h; grant select on *.* to u6@h; grant select on *.* to u7@h; -error ER_PASSWORD_NO_MATCH; grant select on *.* to u8@h; select user,select_priv,plugin,authentication_string from mysql.user where user like 'u_'; diff --git a/mysql-test/main/plugin_auth_qa_1.result b/mysql-test/main/plugin_auth_qa_1.result index dd709fee04c..d2d902cb6a6 100644 --- a/mysql-test/main/plugin_auth_qa_1.result +++ b/mysql-test/main/plugin_auth_qa_1.result @@ -149,13 +149,11 @@ new_user test_plugin_server new_dest plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.plugin', 'new_plugin_server') WHERE user='new_user'; FLUSH PRIVILEGES; -Warnings: -Warning 1524 Plugin 'new_plugin_server' is not loaded SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; User plugin authentication_string new_user new_plugin_server new_dest plug_dest mysql_native_password *939AEE68989794C0F408277411C26055CDF41119 -ERROR 28000: Access denied for user 'new_user'@'localhost' (using password: YES) +ERROR HY000: Plugin 'new_plugin_server' is not loaded UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.plugin', 'test_plugin_server') WHERE user='new_user'; UPDATE mysql.global_priv SET user='new_dest' WHERE user='plug_dest'; FLUSH PRIVILEGES; diff --git a/mysql-test/main/plugin_auth_qa_1.test b/mysql-test/main/plugin_auth_qa_1.test index 81a9155a390..fb577fc178f 100644 --- a/mysql-test/main/plugin_auth_qa_1.test +++ b/mysql-test/main/plugin_auth_qa_1.test @@ -141,7 +141,7 @@ FLUSH PRIVILEGES; --sorted_result SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root'; --disable_query_log ---error ER_ACCESS_DENIED_ERROR +--error ER_PLUGIN_IS_NOT_LOADED connect(plug_user,localhost,new_user,new_dest); --enable_query_log UPDATE mysql.global_priv SET priv=JSON_SET(priv, '$.plugin', 'test_plugin_server') WHERE user='new_user'; diff --git a/plugin/auth_gssapi/gssapi_server.cc b/plugin/auth_gssapi/gssapi_server.cc index a498aba982d..8aa13aac6c9 100644 --- a/plugin/auth_gssapi/gssapi_server.cc +++ b/plugin/auth_gssapi/gssapi_server.cc @@ -145,7 +145,7 @@ int plugin_deinit() } -int auth_server(MYSQL_PLUGIN_VIO *vio,const char *user, size_t userlen, int use_full_name) +int auth_server(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info) { int rc= CR_ERROR; /* return code */ @@ -157,6 +157,9 @@ int auth_server(MYSQL_PLUGIN_VIO *vio,const char *user, size_t userlen, int use_ gss_name_t client_name; gss_buffer_desc client_name_buf, input, output; char *client_name_str; + const char *user= 0; + size_t userlen; + int use_full_name; /* server acquires credential */ major= gss_acquire_cred(&minor, service_name, GSS_C_INDEFINITE, @@ -180,6 +183,21 @@ int auth_server(MYSQL_PLUGIN_VIO *vio,const char *user, size_t userlen, int use_ log_error(0, 0, "fail to read token from client"); goto cleanup; } + if (!user) + { + if (auth_info->auth_string_length > 0) + { + use_full_name= 1; + user= auth_info->auth_string; + userlen= auth_info->auth_string_length; + } + else + { + use_full_name= 0; + user= auth_info->user_name; + userlen= auth_info->user_name_length; + } + } input.length= len; major= gss_accept_sec_context(&minor, &ctxt, cred, &input, diff --git a/plugin/auth_gssapi/server_plugin.cc b/plugin/auth_gssapi/server_plugin.cc index 5db86cffbe4..550ae775e0f 100644 --- a/plugin/auth_gssapi/server_plugin.cc +++ b/plugin/auth_gssapi/server_plugin.cc @@ -64,41 +64,11 @@ unsigned long srv_mech; */ static int gssapi_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info) { - int use_full_name; - const char *user; - int user_len; - - /* No user name yet ? Read the client handshake packet with the user name. */ - if (auth_info->user_name == 0) - { - unsigned char *pkt; - if (vio->read_packet(vio, &pkt) < 0) - return CR_ERROR; - } - /* Send first packet with target name and mech name */ if (vio->write_packet(vio, (unsigned char *)first_packet, first_packet_len)) - { return CR_ERROR; - } - /* Figure out whether to use full name (as given in IDENTIFIED AS clause) - * or just short username auth_string - */ - if (auth_info->auth_string_length > 0) - { - use_full_name= 1; - user= auth_info->auth_string; - user_len= auth_info->auth_string_length; - } - else - { - use_full_name= 0; - user= auth_info->user_name; - user_len= auth_info->user_name_length; - } - - return auth_server(vio, user, user_len, use_full_name); + return auth_server(vio, auth_info); } static int initialize_plugin(void *unused) diff --git a/plugin/auth_gssapi/server_plugin.h b/plugin/auth_gssapi/server_plugin.h index 6284a319d03..84552d3a263 100644 --- a/plugin/auth_gssapi/server_plugin.h +++ b/plugin/auth_gssapi/server_plugin.h @@ -48,4 +48,4 @@ extern char *srv_keytab_path; int plugin_init(); int plugin_deinit(); -int auth_server(MYSQL_PLUGIN_VIO *vio, const char *username, size_t username_len, int use_full_name); +int auth_server(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info); diff --git a/plugin/auth_gssapi/sspi_server.cc b/plugin/auth_gssapi/sspi_server.cc index af78829df6e..44aa5051472 100644 --- a/plugin/auth_gssapi/sspi_server.cc +++ b/plugin/auth_gssapi/sspi_server.cc @@ -140,7 +140,7 @@ static int get_client_name_from_context(CtxtHandle *ctxt, } -int auth_server(MYSQL_PLUGIN_VIO *vio, const char *user, size_t user_len, int compare_full_name) +int auth_server(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *auth_info) { int ret; SECURITY_STATUS sspi_ret; @@ -155,6 +155,8 @@ int auth_server(MYSQL_PLUGIN_VIO *vio, const char *user, size_t user_len, int co SecBuffer outbuf; void* out= NULL; char client_name[MYSQL_USERNAME_LENGTH + 1]; + const char *user= 0; + int compare_full_name; ret= CR_ERROR; SecInvalidateHandle(&cred); @@ -207,6 +209,19 @@ int auth_server(MYSQL_PLUGIN_VIO *vio, const char *user, size_t user_len, int co log_error(SEC_E_OK, "communication error(read)"); goto cleanup; } + if (!user) + { + if (auth_info->auth_string_length > 0) + { + compare_full_name= 1; + user= auth_info->auth_string; + } + else + { + compare_full_name= 0; + user= auth_info->user_name; + } + } inbuf.cbBuffer= len; outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE; sspi_ret= AcceptSecurityContext( diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c index 1ffc3285a3d..56154fb1656 100644 --- a/plugin/auth_pam/auth_pam.c +++ b/plugin/auth_pam/auth_pam.c @@ -36,8 +36,8 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { int p_to_c[2], c_to_p[2]; /* Parent-to-child and child-to-parent pipes. */ pid_t proc_id; - int result= CR_ERROR; - unsigned char field; + int result= CR_ERROR, pkt_len; + unsigned char field, *pkt; PAM_DEBUG((stderr, "PAM: opening pipes.\n")); if (pipe(p_to_c) < 0 || pipe(c_to_p) < 0) @@ -96,6 +96,14 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) close(c_to_p[1]) < 0) goto error_ret; + /* no user name yet ? read the client handshake packet with the user name */ + if (info->user_name == 0) + { + if ((pkt_len= vio->read_packet(vio, &pkt) < 0)) + return CR_ERROR; + } + else + pkt= NULL; PAM_DEBUG((stderr, "PAM: parent sends user data [%s], [%s].\n", info->user_name, info->auth_string)); @@ -140,23 +148,27 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { unsigned char buf[10240]; int buf_len; - unsigned char *pkt; PAM_DEBUG((stderr, "PAM: getting CONV string.\n")); if ((buf_len= read_string(c_to_p[0], (char *) buf, sizeof(buf))) < 0) goto error_ret; - PAM_DEBUG((stderr, "PAM: sending CONV string.\n")); - if (vio->write_packet(vio, buf, buf_len)) - goto error_ret; + if (!pkt || (buf[0] >> 1) != 2) + { + PAM_DEBUG((stderr, "PAM: sending CONV string.\n")); + if (vio->write_packet(vio, buf, buf_len)) + goto error_ret; - PAM_DEBUG((stderr, "PAM: reading CONV answer.\n")); - if ((buf_len= vio->read_packet(vio, &pkt)) < 0) - goto error_ret; + PAM_DEBUG((stderr, "PAM: reading CONV answer.\n")); + if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) + goto error_ret; + } PAM_DEBUG((stderr, "PAM: answering CONV.\n")); - if (write_string(p_to_c[1], pkt, buf_len)) + if (write_string(p_to_c[1], pkt, pkt_len)) goto error_ret; + + pkt= NULL; } break; diff --git a/plugin/auth_pam/auth_pam_v1.c b/plugin/auth_pam/auth_pam_v1.c index 95110a5e310..6e0b2ea9991 100644 --- a/plugin/auth_pam/auth_pam_v1.c +++ b/plugin/auth_pam/auth_pam_v1.c @@ -17,13 +17,21 @@ #include struct param { - unsigned char buf[10240], *ptr; + unsigned char buf[10240], *ptr, *cached; + int cached_len; MYSQL_PLUGIN_VIO *vio; }; static int roundtrip(struct param *param, const unsigned char *buf, int buf_len, unsigned char **pkt) { + if (param->cached && (buf[0] >> 1) == 2) + { + *pkt= param->cached; + param->cached= NULL; + return param->cached_len; + } + param->cached= NULL; if (param->vio->write_packet(param->vio, buf, buf_len)) return -1; return param->vio->read_packet(param->vio, pkt); @@ -35,6 +43,16 @@ static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) { struct param param; param.vio = vio; + + /* no user name yet ? read the client handshake packet with the user name */ + if (info->user_name == 0) + { + if ((param.cached_len= vio->read_packet(vio, ¶m.cached) < 0)) + return CR_ERROR; + } + else + param.cached= NULL; + return pam_auth_base(¶m, info); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 01b560cd59b..b4ceec66a9e 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -170,7 +170,8 @@ public: else dst->plugin= safe_lexcstrdup_root(root, plugin); dst->auth_string= safe_lexcstrdup_root(root, auth_string); - dst->salt= safe_lexcstrdup_root(root, salt); + if (salt.str) + dst->salt= safe_lexcstrdup_root(root, salt); dst->host.hostname= safe_strdup_root(root, host.hostname); dst->default_rolename= safe_lexcstrdup_root(root, default_rolename); bzero(&dst->role_grants, sizeof(role_grants)); @@ -1781,6 +1782,26 @@ static bool validate_password(THD *thd, const LEX_CSTRING &user, return false; } +static int set_user_salt(ACL_USER *acl_user, plugin_ref plugin) +{ + st_mysql_auth *auth= (st_mysql_auth *) plugin_decl(plugin)->info; + if (auth->interface_version >= 0x0202 && acl_user->auth_string.length && + auth->preprocess_hash) + { + uchar buf[MAX_SCRAMBLE_LENGTH]; + size_t len= sizeof(buf); + if (auth->preprocess_hash(acl_user->auth_string.str, + acl_user->auth_string.length, buf, &len)) + return 1; // ER_PASSWD_LENGTH? + acl_user->salt.str= (char*)memdup_root(&acl_memroot, buf, len); + acl_user->salt.length= len; + } + else + acl_user->salt= acl_user->auth_string; + + return 0; +} + /** Fills in ACL_USER::auth_string and ACL_USER::salt fields, as needed @@ -1789,11 +1810,8 @@ static bool validate_password(THD *thd, const LEX_CSTRING &user, Fails if the plain-text password fails validation, if the plugin is not loaded, if the auth_string is invalid. - - Using NULL for a password disables validation - (needed for loading from mysql.user table). */ -static int set_user_auth(THD *thd, ACL_USER *acl_user, const LEX_CSTRING *pwtext) +static int set_user_auth(THD *thd, ACL_USER *acl_user, const LEX_CSTRING &pwtext) { const char *plugin_name= acl_user->plugin.str; bool unlock_plugin= false; @@ -1813,49 +1831,32 @@ static int set_user_auth(THD *thd, ACL_USER *acl_user, const LEX_CSTRING *pwtext st_mysql_auth *auth= (st_mysql_auth *) plugin_decl(plugin)->info; if (auth->interface_version >= 0x0202) { - if (pwtext) + if (auth->hash_password && + validate_password(thd, acl_user->user, pwtext, + acl_user->auth_string.length)) + goto end; + if (pwtext.length) { - if (auth->hash_password && - validate_password(thd, acl_user->user, *pwtext, - acl_user->auth_string.length)) - goto end; - if (pwtext->length) + if (auth->hash_password) { - if (auth->hash_password) - { - char buf[MAX_SCRAMBLE_LENGTH]; - size_t len= sizeof(buf) - 1; - if (auth->hash_password(pwtext->str, pwtext->length, buf, &len)) - goto end; // OOM? - buf[len] = 0; - acl_user->auth_string.str= (char*)memdup_root(&acl_memroot, buf, len+1); - acl_user->auth_string.length= len; - } - else - { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_SET_PASSWORD_AUTH_PLUGIN, - ER_THD(thd, ER_SET_PASSWORD_AUTH_PLUGIN), - acl_user->plugin.str); - } - } - } - - if (acl_user->auth_string.length) - { - if (auth->preprocess_hash) - { - uchar buf[MAX_SCRAMBLE_LENGTH]; - size_t len= sizeof(buf); - if (auth->preprocess_hash(acl_user->auth_string.str, - acl_user->auth_string.length, buf, &len)) - goto end; // ER_PASSWD_LENGTH? - acl_user->salt.str= (char*)memdup_root(&acl_memroot, buf, len); - acl_user->salt.length= len; + char buf[MAX_SCRAMBLE_LENGTH]; + size_t len= sizeof(buf) - 1; + if (auth->hash_password(pwtext.str, pwtext.length, buf, &len)) + goto end; // OOM? + buf[len] = 0; + acl_user->auth_string.str= (char*)memdup_root(&acl_memroot, buf, len+1); + acl_user->auth_string.length= len; } else - acl_user->salt= acl_user->auth_string; + { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_SET_PASSWORD_AUTH_PLUGIN, + ER_THD(thd, ER_SET_PASSWORD_AUTH_PLUGIN), + acl_user->plugin.str); + } } + if (set_user_salt(acl_user, plugin)) + goto end; } res= 0; @@ -1865,6 +1866,34 @@ end: return res; } + +/** + Lazily computes user's salt from the password hash +*/ +static bool set_user_salt_if_needed(ACL_USER *user_copy, plugin_ref plugin) +{ + DBUG_ASSERT(!strcasecmp(user_copy->plugin.str, plugin_name(plugin)->str)); + + if (user_copy->salt.str) + return 0; // already done + + if (set_user_salt(user_copy, plugin)) + return 1; + + mysql_mutex_lock(&acl_cache->lock); + ACL_USER *user= find_user_exact(user_copy->host.hostname, user_copy->user.str); + // make sure the user wasn't altered or dropped meanwhile + if (user && !user->salt.str && + user->plugin.length == user_copy->plugin.length && + user->auth_string.length == user_copy->auth_string.length && + !memcmp(user->plugin.str, user_copy->plugin.str, user->plugin.length) && + !memcmp(user->auth_string.str, user_copy->auth_string.str, user->auth_string.length)) + user->salt= user_copy->salt; + mysql_mutex_unlock(&acl_cache->lock); + return 0; +} + + /** Fix ACL::plugin pointer to point to a hard-coded string, if appropriate @@ -2128,12 +2157,6 @@ static bool acl_load(THD *thd, const Grant_tables& tables) user.default_rolename.str= user_table.get_default_role(&acl_memroot); user.default_rolename.length= safe_strlen(user.default_rolename.str); - - if (set_user_auth(thd, &user, NULL)) - { - thd->clear_error(); // the warning is still issued - continue; - } } push_new_user(user); } @@ -2852,7 +2875,7 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, const ACL_USER *from, acl_user->hostname_length= combo.host.length; acl_user->sort= get_sort(2, acl_user->host.hostname, acl_user->user.str); acl_user->plugin= native_password_plugin_name; - acl_user->salt= acl_user->auth_string= empty_clex_str; + acl_user->auth_string= empty_clex_str; my_init_dynamic_array(&acl_user->role_grants, sizeof(ACL_USER *), 0, 8, MYF(0)); } @@ -2863,7 +2886,7 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, const ACL_USER *from, acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, combo.auth); if (fix_user_plugin_ptr(acl_user)) acl_user->plugin= safe_lexcstrdup_root(&acl_memroot, combo.plugin); - if (set_user_auth(thd, acl_user, &combo.pwtext)) + if (set_user_auth(thd, acl_user, combo.pwtext)) return 1; } acl_user->access= privileges; @@ -3429,7 +3452,7 @@ bool change_password(THD *thd, LEX_USER *user) } acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, user->auth); - if (set_user_auth(thd, acl_user, &user->pwtext)) + if (set_user_auth(thd, acl_user, user->pwtext)) { mysql_mutex_unlock(&acl_cache->lock); goto end; @@ -11275,10 +11298,10 @@ static int show_database_grants(THD *thd, SHOW_VAR *var, char *buff, } #else +static bool set_user_salt_if_needed(ACL_USER *, plugin_ref) +{ return 0; } bool check_grant(THD *, ulong, TABLE_LIST *, bool, uint, bool) -{ - return 0; -} +{ return 0; } #endif /*NO_EMBEDDED_ACCESS_CHECKS */ SHOW_VAR acl_statistics[] = { @@ -12432,12 +12455,6 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio) DBUG_RETURN (1); } - mpvio->auth_info.user_name= sctx->user; - mpvio->auth_info.user_name_length= (uint)strlen(sctx->user); - mpvio->auth_info.auth_string= mpvio->acl_user->salt.str; - mpvio->auth_info.auth_string_length= (unsigned long) mpvio->acl_user->salt.length; - strmake_buf(mpvio->auth_info.authenticated_as, mpvio->acl_user->user.str); - DBUG_PRINT("info", ("exit: user=%s, auth_string=%s, authenticated as=%s" "plugin=%s", mpvio->auth_info.user_name, @@ -12609,8 +12626,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) } if ((thd->client_capabilities & CLIENT_CONNECT_ATTRS) && - read_client_connect_attrs(&next_field, end, - thd->charset())) + read_client_connect_attrs(&next_field, end, thd->charset())) { my_message(ER_UNKNOWN_COM_ERROR, ER_THD(thd, ER_UNKNOWN_COM_ERROR), MYF(0)); @@ -12970,7 +12986,7 @@ static int server_mpvio_write_packet(MYSQL_PLUGIN_VIO *param, */ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) { - MPVIO_EXT *mpvio= (MPVIO_EXT *) param; + MPVIO_EXT * const mpvio= (MPVIO_EXT *) param; ulong pkt_len; DBUG_ENTER("server_mpvio_read_packet"); if (mpvio->packets_written == 0) @@ -13001,11 +13017,11 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) client_auth_plugin) == 0) { mpvio->status= MPVIO_EXT::FAILURE; + pkt_len= mpvio->cached_client_reply.pkt_len; *buf= (uchar*) mpvio->cached_client_reply.pkt; mpvio->cached_client_reply.pkt= 0; mpvio->packets_read++; - - DBUG_RETURN ((int) mpvio->cached_client_reply.pkt_len); + goto done; } /* @@ -13039,6 +13055,16 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) else *buf= mpvio->auth_info.thd->net.read_pos; +done: + if (set_user_salt_if_needed(mpvio->acl_user, mpvio->plugin)) + goto err; + + mpvio->auth_info.user_name= mpvio->auth_info.thd->security_ctx->user; + mpvio->auth_info.user_name_length= (uint)strlen(mpvio->auth_info.user_name); + mpvio->auth_info.auth_string= mpvio->acl_user->salt.str; + mpvio->auth_info.auth_string_length= (ulong) mpvio->acl_user->salt.length; + strmake_buf(mpvio->auth_info.authenticated_as, mpvio->acl_user->user.str); + DBUG_RETURN((int)pkt_len); err: @@ -13179,6 +13205,7 @@ static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name, plugin_ref plugin= get_auth_plugin(thd, *auth_plugin_name, &unlock_plugin); mpvio->plugin= plugin; + mpvio->auth_info.user_name= NULL; old_status= mpvio->status; if (plugin) From 103a32fdd36843ec45c8ac1991abb1cf4cae1eb6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 18 Jan 2019 19:28:44 +0100 Subject: [PATCH 29/91] ed25519: better error message for an incorrect password hash --- mysql-test/suite/plugins/r/auth_ed25519.result | 4 ++++ mysql-test/suite/plugins/t/auth_ed25519.test | 4 ++++ plugin/auth_ed25519/server_ed25519.c | 9 ++++++++- sql/sql_acl.cc | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/plugins/r/auth_ed25519.result b/mysql-test/suite/plugins/r/auth_ed25519.result index 7b26530ed12..a7008b318ba 100644 --- a/mysql-test/suite/plugins/r/auth_ed25519.result +++ b/mysql-test/suite/plugins/r/auth_ed25519.result @@ -39,6 +39,10 @@ show grants for test1@localhost; Grants for test1@localhost GRANT USAGE ON *.* TO 'test1'@'localhost' IDENTIFIED VIA ed25519 USING 'ZIgUREUg5PVgQ6LskhXmO+eZLS0nC8be6HPjYWR4YJY' drop user test1@localhost; +create user test1@localhost identified via ed25519 using 'foo'; +ERROR HY000: Password hash should be 43 characters long +create user test1@localhost identified via ed25519 using '>>>1234567890123456789012345678901234567890'; +ERROR HY000: Password hash should be base64 encoded create user test1@localhost identified via ed25519 using password('foo'); show grants for test1@localhost; Grants for test1@localhost diff --git a/mysql-test/suite/plugins/t/auth_ed25519.test b/mysql-test/suite/plugins/t/auth_ed25519.test index b8a7b996f65..8e0bdd1d460 100644 --- a/mysql-test/suite/plugins/t/auth_ed25519.test +++ b/mysql-test/suite/plugins/t/auth_ed25519.test @@ -29,6 +29,10 @@ let $pwd=`select ed25519_password("secret")`; eval create user test1@localhost identified via ed25519 using '$pwd'; show grants for test1@localhost; drop user test1@localhost; +--error ER_PASSWD_LENGTH +create user test1@localhost identified via ed25519 using 'foo'; +--error ER_PASSWD_LENGTH +create user test1@localhost identified via ed25519 using '>>>1234567890123456789012345678901234567890'; create user test1@localhost identified via ed25519 using password('foo'); show grants for test1@localhost; select ed25519_password('foo'); diff --git a/plugin/auth_ed25519/server_ed25519.c b/plugin/auth_ed25519/server_ed25519.c index 06c25558653..d2e9e70a9b9 100644 --- a/plugin/auth_ed25519/server_ed25519.c +++ b/plugin/auth_ed25519/server_ed25519.c @@ -15,6 +15,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #include +#include #include "common.h" #if !defined(__attribute__) && !defined(__GNUC__) @@ -77,12 +78,18 @@ static int digest_to_binary(const char *d, size_t dlen, char pw[PASSWORD_LEN_BUF]; if (*blen < CRYPTO_PUBLICKEYBYTES || dlen != PASSWORD_LEN) + { + my_printf_error(ER_PASSWD_LENGTH, "Password hash should be %d characters long", 0, PASSWORD_LEN); return 1; + } *blen= CRYPTO_PUBLICKEYBYTES; memcpy(pw, d, PASSWORD_LEN); pw[PASSWORD_LEN]= '='; - return my_base64_decode(pw, PASSWORD_LEN_BUF, b, 0, 0) != CRYPTO_PUBLICKEYBYTES; + if (my_base64_decode(pw, PASSWORD_LEN_BUF, b, 0, 0) == CRYPTO_PUBLICKEYBYTES) + return 0; + my_printf_error(ER_PASSWD_LENGTH, "Password hash should be base64 encoded", 0); + return 1; } static struct st_mysql_auth info = diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index b4ceec66a9e..1880bc7246a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1792,7 +1792,7 @@ static int set_user_salt(ACL_USER *acl_user, plugin_ref plugin) size_t len= sizeof(buf); if (auth->preprocess_hash(acl_user->auth_string.str, acl_user->auth_string.length, buf, &len)) - return 1; // ER_PASSWD_LENGTH? + return 1; acl_user->salt.str= (char*)memdup_root(&acl_memroot, buf, len); acl_user->salt.length= len; } From 9b3f177c6d4bda28edb0f3259e6417c47c62fe39 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 10 Jan 2019 13:51:28 +0100 Subject: [PATCH 30/91] avoid unintentional %union size increases --- sql/sql_yacc.yy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8f62dca4aec..f689180977c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -788,6 +788,8 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) } %{ +/* avoid unintentional %union size increases, it's what a parser stack made of */ +static_assert(sizeof(YYSTYPE) == sizeof(void*)*2+8, "%union size check"); bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %} From b8344be4fac0b8e7297a556e89f62dd6a6bafa47 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 14 Jan 2019 22:22:54 +0100 Subject: [PATCH 31/91] cleanup --- sql/sql_acl.cc | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 1880bc7246a..aa7b08092b5 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -624,7 +624,6 @@ static int acl_user_compare(const ACL_USER *a, const ACL_USER *b); static void rebuild_acl_users(); static int acl_db_compare(const ACL_DB *a, const ACL_DB *b); static void rebuild_acl_dbs(); -static ulong get_sort(uint count,...); static void init_check_host(void); static void rebuild_check_host(void); static void rebuild_role_grants(void); @@ -3980,13 +3979,12 @@ static bool test_if_create_new_users(THD *thd) ****************************************************************************/ static int replace_user_table(THD *thd, const User_table &user_table, - LEX_USER *combo, - ulong rights, bool revoke_grant, - bool can_create_user, bool no_auto_create) + LEX_USER * const combo, ulong rights, + const bool revoke_grant, const bool can_create_user, + const bool no_auto_create) { int error = -1; bool old_row_exists=0; - char what= (revoke_grant) ? 'N' : 'Y'; uchar user_key[MAX_KEY_LENGTH]; bool handle_as_role= combo->is_role(); LEX *lex= thd->lex; @@ -4003,11 +4001,9 @@ static int replace_user_table(THD *thd, const User_table &user_table, table->key_info->key_length); if (table->file->ha_index_read_idx_map(table->record[0], 0, user_key, - HA_WHOLE_KEY, - HA_READ_KEY_EXACT)) + HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { - /* what == 'N' means revoke */ - if (what == 'N') + if (revoke_grant) { my_error(ER_NONEXISTING_GRANT, MYF(0), combo->user.str, combo->host.str); goto end; @@ -4220,13 +4216,13 @@ end: static int replace_db_table(TABLE *table, const char *db, const LEX_USER &combo, - ulong rights, bool revoke_grant) + ulong rights, const bool revoke_grant) { uint i; ulong priv,store_rights; bool old_row_exists=0; int error; - char what= (revoke_grant) ? 'N' : 'Y'; + char what= revoke_grant ? 'N' : 'Y'; uchar user_key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_db_table"); @@ -4255,7 +4251,7 @@ static int replace_db_table(TABLE *table, const char *db, HA_WHOLE_KEY, HA_READ_KEY_EXACT)) { - if (what == 'N') + if (revoke_grant) { // no row, no revoke my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str); goto abort; From 9c9b4590b68d0b655f26191f93d7ed4e6497ce06 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sun, 20 Jan 2019 00:59:11 +0100 Subject: [PATCH 32/91] Fix the bug introduced in MDEV-17658 if auth_root_socket is set, root user should be using unix_socket Followup for 4abb8216a05 --- scripts/mysql_system_tables_data.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql index f14dcf01594..60867fc2bc3 100644 --- a/scripts/mysql_system_tables_data.sql +++ b/scripts/mysql_system_tables_data.sql @@ -37,7 +37,7 @@ REPLACE INTO tmp_user_nopasswd SELECT @current_hostname,'root',@all_privileges F REPLACE INTO tmp_user_nopasswd VALUES ('127.0.0.1','root',@all_privileges); REPLACE INTO tmp_user_nopasswd VALUES ('::1','root',@all_privileges); -- More secure root account using unix socket auth. -INSERT INTO tmp_user_socket VALUES ('localhost',IFNULL(@auth_root_socket, 'root'),@all_privileges); +INSERT INTO tmp_user_socket VALUES ('localhost',IFNULL(@auth_root_socket, 'root'),json_set(@all_privileges, '$.plugin', 'unix_socket')); IF @auth_root_socket is not null THEN IF not exists(select 1 from information_schema.plugins where plugin_name='unix_socket') THEN INSTALL SONAME 'auth_socket'; END IF; END IF; From 3416e8ac9a0f614846d2f6c1cc3fcb7052c53f4e Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 1 Feb 2019 15:37:31 +0100 Subject: [PATCH 33/91] cleanup: sys_vars.cc add DEPRECATED() warning for variables with "deprecated" in the help text. Remove redundant initializers. --- mysql-test/suite/galera/r/partition.result | 8 +++ .../suite/sys_vars/r/sysvars_wsrep.result | 2 +- .../r/wsrep_load_data_splitting_basic.result | 12 ++++ sql/sys_vars.cc | 56 +++++++++---------- sql/sys_vars.ic | 2 +- 5 files changed, 47 insertions(+), 33 deletions(-) diff --git a/mysql-test/suite/galera/r/partition.result b/mysql-test/suite/galera/r/partition.result index e34028ab04f..213f9dfdbab 100644 --- a/mysql-test/suite/galera/r/partition.result +++ b/mysql-test/suite/galera/r/partition.result @@ -118,6 +118,8 @@ connection node_1; # Case 1: wsrep_load_data_splitting = ON & LOAD DATA with 20002 # entries. SET GLOBAL wsrep_load_data_splitting = ON; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; connection node_2; @@ -130,6 +132,8 @@ DROP TABLE t1; # Case 2: wsrep_load_data_splitting = ON & LOAD DATA with 101 entries. connection node_1; SET GLOBAL wsrep_load_data_splitting = ON; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; connection node_2; @@ -143,6 +147,8 @@ DROP TABLE t1; # entries. connection node_1; SET GLOBAL wsrep_load_data_splitting = OFF; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=INNODB PARTITION BY HASH(pk) PARTITIONS 2; connection node_2; @@ -154,6 +160,8 @@ AS_EXPECTED_1_or_2 DROP TABLE t1; connection node_1; SET GLOBAL wsrep_load_data_splitting = 1;; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release disconnect node_2; disconnect node_1; # End of test diff --git a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result index ac83a0a8c7f..dd3e70c587d 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result +++ b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result @@ -232,7 +232,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE ON VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT To commit LOAD DATA transaction after every 10K rows inserted (deprecating) +VARIABLE_COMMENT To commit LOAD DATA transaction after every 10K rows inserted (deprecated) NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL diff --git a/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result b/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result index 687934a7705..d373a3832d5 100644 --- a/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result +++ b/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result @@ -12,24 +12,34 @@ SELECT @@global.wsrep_load_data_splitting; SELECT @@session.wsrep_load_data_splitting; ERROR HY000: Variable 'wsrep_load_data_splitting' is a GLOBAL variable SET @@global.wsrep_load_data_splitting=OFF; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release SELECT @@global.wsrep_load_data_splitting; @@global.wsrep_load_data_splitting 0 SET @@global.wsrep_load_data_splitting=ON; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release SELECT @@global.wsrep_load_data_splitting; @@global.wsrep_load_data_splitting 1 # valid values SET @@global.wsrep_load_data_splitting='OFF'; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release SELECT @@global.wsrep_load_data_splitting; @@global.wsrep_load_data_splitting 0 SET @@global.wsrep_load_data_splitting=ON; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release SELECT @@global.wsrep_load_data_splitting; @@global.wsrep_load_data_splitting 1 SET @@global.wsrep_load_data_splitting=default; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release SELECT @@global.wsrep_load_data_splitting; @@global.wsrep_load_data_splitting 1 @@ -42,4 +52,6 @@ ERROR 42000: Variable 'wsrep_load_data_splitting' can't be set to the value of ' # restore the initial value SET @@global.wsrep_load_data_splitting = @wsrep_load_data_splitting_global_saved; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release # End of test diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 1c8a1dd67ba..7241685fb61 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -598,7 +598,7 @@ static Sys_var_mybool Sys_explicit_defaults_for_timestamp( "as NULL with DEFAULT NULL attribute, Without this option, " "TIMESTAMP columns are NOT NULL and have implicit DEFAULT clauses.", READ_ONLY GLOBAL_VAR(opt_explicit_defaults_for_timestamp), - CMD_LINE(OPT_ARG), DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG); + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); static Sys_var_ulonglong Sys_bulk_insert_buff_size( @@ -2156,7 +2156,7 @@ static Sys_var_bit Sys_skip_parallel_replication( "retry for transactions that are likely to cause a conflict if " "replicated in parallel.", SESSION_ONLY(option_bits), NO_CMD_LINE, OPTION_RPL_SKIP_PARALLEL, - DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG); + DEFAULT(FALSE)); static bool @@ -2252,7 +2252,9 @@ static Sys_var_ulong Sys_max_long_data_size( READ_ONLY GLOBAL_VAR(max_long_data_size), CMD_LINE(REQUIRED_ARG, OPT_MAX_LONG_DATA_SIZE), VALID_RANGE(1024, UINT_MAX32), DEFAULT(1024*1024), - BLOCK_SIZE(1)); + BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(0), ON_UPDATE(0), + DEPRECATED("'@@max_allowed_packet'")); static PolyLock_mutex PLock_prepared_stmt_count(&LOCK_prepared_stmt_count); static Sys_var_uint Sys_max_prepared_stmt_count( @@ -2537,7 +2539,7 @@ static Sys_var_flagset Sys_optimizer_switch( "Fine-tune the optimizer behavior", SESSION_VAR(optimizer_switch), CMD_LINE(REQUIRED_ARG), optimizer_switch_names, DEFAULT(OPTIMIZER_SWITCH_DEFAULT), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_optimizer_switch)); static Sys_var_charptr Sys_pid_file( @@ -2891,7 +2893,7 @@ static Sys_var_ulong Sys_query_cache_limit( "Don't cache results that are bigger than this", GLOBAL_VAR(query_cache_limit), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, UINT_MAX), DEFAULT(1024*1024), BLOCK_SIZE(1), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_query_cache_limit)); static bool fix_qcache_min_res_unit(sys_var *self, THD *thd, enum_var_type type) @@ -3762,7 +3764,7 @@ static Sys_var_mybool Sys_timed_mutexes( "timed_mutexes", "Specify whether to time mutexes. Deprecated, has no effect.", GLOBAL_VAR(timed_mutexes), CMD_LINE(OPT_ARG), DEFAULT(0), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), ON_UPDATE(NULL), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0), DEPRECATED("")); static Sys_var_charptr Sys_version( @@ -5336,7 +5338,7 @@ static Sys_var_ulong Sys_wsrep_slave_threads( GLOBAL_VAR(wsrep_slave_threads), CMD_LINE(REQUIRED_ARG), VALID_RANGE(1, 512), DEFAULT(1), BLOCK_SIZE(1), &PLock_wsrep_slave_threads, NOT_IN_BINLOG, - ON_CHECK(NULL), + ON_CHECK(0), ON_UPDATE(wsrep_slave_threads_update)); static Sys_var_charptr Sys_wsrep_dbug_option( @@ -5518,9 +5520,10 @@ static Sys_var_ulong Sys_wsrep_mysql_replication_bundle( static Sys_var_mybool Sys_wsrep_load_data_splitting( "wsrep_load_data_splitting", "To commit LOAD DATA " - "transaction after every 10K rows inserted (deprecating)", + "transaction after every 10K rows inserted (deprecated)", GLOBAL_VAR(wsrep_load_data_splitting), - CMD_LINE(OPT_ARG), DEFAULT(TRUE)); + CMD_LINE(OPT_ARG), DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(0), ON_UPDATE(0), DEPRECATED("")); static Sys_var_mybool Sys_wsrep_slave_FK_checks( "wsrep_slave_FK_checks", "Should slave thread do " @@ -5565,14 +5568,13 @@ extern const char *wsrep_SR_store_types[]; static Sys_var_enum Sys_wsrep_SR_store( "wsrep_SR_store", "Storage for streaming replication fragments", READ_ONLY GLOBAL_VAR(wsrep_SR_store_type), CMD_LINE(REQUIRED_ARG), - wsrep_SR_store_types, DEFAULT(WSREP_SR_STORE_TABLE), - NO_MUTEX_GUARD, NOT_IN_BINLOG); + wsrep_SR_store_types, DEFAULT(WSREP_SR_STORE_TABLE)); static Sys_var_mybool Sys_wsrep_dirty_reads( "wsrep_dirty_reads", "Allow reads even when the node is not in the primary component.", SESSION_VAR(wsrep_dirty_reads), CMD_LINE(OPT_ARG), - DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG); + DEFAULT(FALSE)); static Sys_var_uint Sys_wsrep_ignore_apply_errors ( "wsrep_ignore_apply_errors", "Ignore replication errors", @@ -5585,8 +5587,7 @@ static Sys_var_uint Sys_wsrep_gtid_domain_id( "used as gtid_domain_id for galera transactions and also copied to the " "joiner nodes during state transfer. It is ignored, otherwise.", GLOBAL_VAR(wsrep_gtid_domain_id), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(0, UINT_MAX32), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, - NOT_IN_BINLOG); + VALID_RANGE(0, UINT_MAX32), DEFAULT(0), BLOCK_SIZE(1)); static Sys_var_mybool Sys_wsrep_gtid_mode( "wsrep_gtid_mode", "Automatically update the (joiner) node's " @@ -5617,7 +5618,7 @@ static Sys_var_ulong Sys_host_cache_size( CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 65536), DEFAULT(HOST_CACHE_SIZE), BLOCK_SIZE(1), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_host_cache_size)); vio_keepalive_opts opt_vio_keepalive; @@ -5627,30 +5628,24 @@ static Sys_var_int Sys_keepalive_time( "Timeout, in milliseconds, with no activity until the first TCP keep-alive packet is sent." "If set to 0, system dependent default is used.", AUTO_SET GLOBAL_VAR(opt_vio_keepalive.idle), - CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, INT_MAX32/1000), - DEFAULT(0), - BLOCK_SIZE(1), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL)); + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, INT_MAX32/1000), DEFAULT(0), + BLOCK_SIZE(1)); static Sys_var_int Sys_keepalive_interval( "tcp_keepalive_interval", "The interval, in seconds, between when successive keep-alive packets are sent if no acknowledgement is received." "If set to 0, system dependent default is used.", AUTO_SET GLOBAL_VAR(opt_vio_keepalive.interval), - CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, INT_MAX32/1000), - DEFAULT(0), - BLOCK_SIZE(1), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL)); + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, INT_MAX32/1000), DEFAULT(0), + BLOCK_SIZE(1)); static Sys_var_int Sys_keepalive_probes( "tcp_keepalive_probes", "The number of unacknowledged probes to send before considering the connection dead and notifying the application layer." "If set to 0, system dependent default is used.", AUTO_SET GLOBAL_VAR(opt_vio_keepalive.probes), - CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, INT_MAX32/1000), - DEFAULT(0), - BLOCK_SIZE(1), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL)); + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, INT_MAX32/1000), DEFAULT(0), + BLOCK_SIZE(1)); static bool update_tcp_nodelay(sys_var *self, THD *thd, @@ -6062,14 +6057,14 @@ static Sys_var_mybool Sys_mysql56_temporal_format( "mysql56_temporal_format", "Use MySQL-5.6 (instead of MariaDB-5.3) format for TIME, DATETIME, TIMESTAMP columns.", GLOBAL_VAR(opt_mysql56_temporal_format), - CMD_LINE(OPT_ARG), DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG); + CMD_LINE(OPT_ARG), DEFAULT(TRUE)); static Sys_var_mybool Sys_strict_password_validation( "strict_password_validation", "When password validation plugins are enabled, reject passwords " "that cannot be validated (passwords specified as a hash)", GLOBAL_VAR(strict_password_validation), - CMD_LINE(OPT_ARG), DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG); + CMD_LINE(OPT_ARG), DEFAULT(TRUE)); #ifdef HAVE_MMAP static Sys_var_ulong Sys_log_tc_size( @@ -6096,8 +6091,7 @@ static Sys_var_sesvartrack Sys_track_session_sys_vars( "Track changes in registered system variables. ", CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, DEFAULT("autocommit,character_set_client,character_set_connection," - "character_set_results,time_zone"), - NO_MUTEX_GUARD); + "character_set_results,time_zone")); static bool update_session_track_schema(sys_var *self, THD *thd, enum_var_type type) diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index 1c41cc22411..398dbb98455 100644 --- a/sql/sys_vars.ic +++ b/sql/sys_vars.ic @@ -596,7 +596,7 @@ public: const char *comment, CMD_LINE getopt, enum charset_enum is_os_charset_arg, - const char *def_val, PolyLock *lock) : + const char *def_val, PolyLock *lock= 0) : Sys_var_charptr_base(name_arg, comment, SESSION_VAR(session_track_system_variables), getopt, is_os_charset_arg, def_val, lock, From 798d1a9ddf159941228ac9c452c1384197d1aef0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 31 Jan 2019 22:02:12 +0100 Subject: [PATCH 34/91] upgrade C/C to 3.1 --- libmariadb | 2 +- mysql-test/suite/unit/suite.pm | 2 ++ plugin/auth_ed25519/CMakeLists.txt | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libmariadb b/libmariadb index 34f8887af03..a4effc462dd 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 34f8887af03d022416dd6593de91d0706e57f46b +Subproject commit a4effc462ddb80b61ebb559d48b50fa8d6c0ed64 diff --git a/mysql-test/suite/unit/suite.pm b/mysql-test/suite/unit/suite.pm index c8180c59240..b7a1f9ae871 100644 --- a/mysql-test/suite/unit/suite.pm +++ b/mysql-test/suite/unit/suite.pm @@ -44,6 +44,8 @@ sub start_test { my (@ctest_list)= `cd "$bin" && ctest $ctest_vs --show-only --verbose`; return "No ctest" if $?; + $ENV{MYSQL_TEST_PLUGINDIR}=$::plugindir; + my ($command, %tests, $prefix); for (@ctest_list) { chomp; diff --git a/plugin/auth_ed25519/CMakeLists.txt b/plugin/auth_ed25519/CMakeLists.txt index 73d8eeb208b..ffd2523d1af 100644 --- a/plugin/auth_ed25519/CMakeLists.txt +++ b/plugin/auth_ed25519/CMakeLists.txt @@ -24,8 +24,8 @@ ENDIF() MYSQL_ADD_PLUGIN(auth_ed25519 server_ed25519.c ${REF10_SOURCES} MODULE_ONLY) # client plugin and unit test ed25519-t can use the library -MYSQL_ADD_PLUGIN(client_ed25519 client_ed25519.c MODULE_ONLY - CLIENT LINK_LIBRARIES mysys_ssl ref10 COMPONENT ClientPlugins) +#MYSQL_ADD_PLUGIN(client_ed25519 client_ed25519.c MODULE_ONLY +# CLIENT LINK_LIBRARIES mysys_ssl ref10 COMPONENT ClientPlugins) IF(WITH_UNIT_TESTS) MY_ADD_TESTS(ed25519 LINK_LIBRARIES mysys ref10) From 5b15cc613ec60f44003dd7d2fdb6421d220b6ee9 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 10 Jan 2019 13:51:51 +0100 Subject: [PATCH 35/91] MDEV-11340 Allow multiple alternative authentication methods for the same user introduce the syntax ... IDENTIFIED { WITH | VIA } plugin [ { USING | AS } auth ] [ OR plugin [ { USING | AS } auth ] [ OR ... ]] Server will try auth plugins in the specified order until the first success. No protocol changes, server uses the existing "switch plugin" packet. The auth chain is stored in json as "auth_or":[{"plugin":"xxx","authentication_string":"yyy"}, {}, {"plugin":"foo","authentication_string":"bar"}, ...], "plugin":"aaa", "authentication_string":"bbb" Note: * "auth_or" implies that there might be "auth_and" someday; * one entry in the array is an empty object, meaning to take plugin/auth from the main json object. This preserves compatibility with the existing mysql.global_priv table and with the mysql.user view. This entry is preferrably a mysql_native_password plugin for a non-empty mysql.user.password column. SET PASSWORD is supported and changes the password for the *first* plugin in the chain that has a notion of a "password" --- libmariadb | 2 +- mysql-test/main/alter_user.result | 2 +- mysql-test/suite/plugins/r/multiauth.result | 170 ++++ mysql-test/suite/plugins/t/multiauth.test | 179 ++++ .../mysql-test/auth_gssapi/multiauth.result | 34 + .../mysql-test/auth_gssapi/multiauth.test | 36 + sql/sql_acl.cc | 809 +++++++++++------- sql/sql_class.cc | 4 +- sql/sql_parse.cc | 7 +- sql/sql_yacc.yy | 107 ++- sql/sql_yacc_ora.yy | 107 ++- sql/structs.h | 23 +- 12 files changed, 1061 insertions(+), 419 deletions(-) create mode 100644 mysql-test/suite/plugins/r/multiauth.result create mode 100644 mysql-test/suite/plugins/t/multiauth.test create mode 100644 plugin/auth_gssapi/mysql-test/auth_gssapi/multiauth.result create mode 100644 plugin/auth_gssapi/mysql-test/auth_gssapi/multiauth.test diff --git a/libmariadb b/libmariadb index a4effc462dd..1e4b08bd298 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit a4effc462ddb80b61ebb559d48b50fa8d6c0ed64 +Subproject commit 1e4b08bd2989c664f6f43e0dbb2c71be9552bc8c diff --git a/mysql-test/main/alter_user.result b/mysql-test/main/alter_user.result index cc3c4a43ffe..cae864fa437 100644 --- a/mysql-test/main/alter_user.result +++ b/mysql-test/main/alter_user.result @@ -65,7 +65,7 @@ alter user foo identified with 'somecoolplugin'; ERROR HY000: Operation ALTER USER failed for 'foo'@'%' show warnings; Level Code Message -Warning 1524 Plugin 'somecoolplugin' is not loaded +Error 1524 Plugin 'somecoolplugin' is not loaded Error 1396 Operation ALTER USER failed for 'foo'@'%' alter user foo identified with 'mysql_old_password'; select * from mysql.user where user = 'foo'; diff --git a/mysql-test/suite/plugins/r/multiauth.result b/mysql-test/suite/plugins/r/multiauth.result new file mode 100644 index 00000000000..998e6d4dce7 --- /dev/null +++ b/mysql-test/suite/plugins/r/multiauth.result @@ -0,0 +1,170 @@ +install soname 'auth_socket'; +install soname 'auth_ed25519'; +create user USER identified via unix_socket OR mysql_native_password as password("GOOD"); +create user mysqltest1 identified via unix_socket OR mysql_native_password as password("good"); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA unix_socket OR mysql_native_password USING '*8409037B3E362D6DAE24C8E667F4D3B66716144E' +# name match = ok +select user(), current_user(), database(); +user() current_user() database() +USER@localhost USER@% test +# name does not match, password good = ok +select user(), current_user(), database(); +user() current_user() database() +mysqltest1@localhost mysqltest1@% test +# name does not match, password bad = failure +drop user USER, mysqltest1; +create user USER identified via mysql_native_password as password("GOOD") OR unix_socket; +create user mysqltest1 identified via mysql_native_password as password("good") OR unix_socket; +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA mysql_native_password USING '*8409037B3E362D6DAE24C8E667F4D3B66716144E' OR unix_socket +# name match = ok +select user(), current_user(), database(); +user() current_user() database() +USER@localhost USER@% test +# name does not match, password good = ok +select user(), current_user(), database(); +user() current_user() database() +mysqltest1@localhost mysqltest1@% test +# name does not match, password bad = failure +drop user USER, mysqltest1; +create user USER identified via unix_socket OR ed25519 as password("GOOD"); +create user mysqltest1 identified via unix_socket OR ed25519 as password("good"); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA unix_socket OR ed25519 USING 'F4aF8bw7130VaRbdLCl4f/P/wkjDmgJXwWvpJ5gmsZc' +# name match = ok +select user(), current_user(), database(); +user() current_user() database() +USER@localhost USER@% test +# name does not match, password good = ok +select user(), current_user(), database(); +user() current_user() database() +mysqltest1@localhost mysqltest1@% test +# name does not match, password bad = failure +drop user USER, mysqltest1; +create user USER identified via ed25519 as password("GOOD") OR unix_socket; +create user mysqltest1 identified via ed25519 as password("good") OR unix_socket; +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA ed25519 USING 'F4aF8bw7130VaRbdLCl4f/P/wkjDmgJXwWvpJ5gmsZc' OR unix_socket +# name match = ok +select user(), current_user(), database(); +user() current_user() database() +USER@localhost USER@% test +# name does not match, password good = ok +select user(), current_user(), database(); +user() current_user() database() +mysqltest1@localhost mysqltest1@% test +# name does not match, password bad = failure +drop user USER, mysqltest1; +create user USER identified via ed25519 as password("GOOD") OR unix_socket OR mysql_native_password as password("works"); +create user mysqltest1 identified via ed25519 as password("good") OR unix_socket OR mysql_native_password as password("works"); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA ed25519 USING 'F4aF8bw7130VaRbdLCl4f/P/wkjDmgJXwWvpJ5gmsZc' OR unix_socket OR mysql_native_password USING '*7D8C3DF236D9163B6C274A9D47704BC496988460' +# name match = ok +select user(), current_user(), database(); +user() current_user() database() +USER@localhost USER@% test +# name does not match, password good = ok +select user(), current_user(), database(); +user() current_user() database() +mysqltest1@localhost mysqltest1@% test +# name does not match, second password works = ok +select user(), current_user(), database(); +user() current_user() database() +mysqltest1@localhost mysqltest1@% test +# name does not match, password bad = failure +drop user USER, mysqltest1; +create user mysqltest1 identified via mysql_native_password as password("good") OR mysql_native_password as password("works"); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA mysql_native_password USING '*8409037B3E362D6DAE24C8E667F4D3B66716144E' OR mysql_native_password USING '*7D8C3DF236D9163B6C274A9D47704BC496988460' +# password good = ok +select user(), current_user(), database(); +user() current_user() database() +mysqltest1@localhost mysqltest1@% test +# second password works = ok +select user(), current_user(), database(); +user() current_user() database() +mysqltest1@localhost mysqltest1@% test +# password bad = failure +drop user mysqltest1; +create user mysqltest1 identified via ed25519 as password("good") OR unix_socket OR mysql_native_password as password("works"); +show grants for mysqltest1; +Grants for mysqltest1@% +GRANT USAGE ON *.* TO 'mysqltest1'@'%' IDENTIFIED VIA ed25519 USING 'F4aF8bw7130VaRbdLCl4f/P/wkjDmgJXwWvpJ5gmsZc' OR unix_socket OR mysql_native_password USING '*7D8C3DF236D9163B6C274A9D47704BC496988460' +select json_detailed(priv) from mysql.global_priv where user='mysqltest1'; +json_detailed(priv) +{ + "access": 0, + "plugin": "mysql_native_password", + "authentication_string": "*7D8C3DF236D9163B6C274A9D47704BC496988460", + "auth_or": + [ + + { + "plugin": "ed25519", + "authentication_string": "F4aF8bw7130VaRbdLCl4f/P/wkjDmgJXwWvpJ5gmsZc" + }, + + { + "plugin": "unix_socket" + }, + + { + } + ] +} +select password,plugin,authentication_string from mysql.user where user='mysqltest1'; +Password plugin authentication_string +*7D8C3DF236D9163B6C274A9D47704BC496988460 mysql_native_password *7D8C3DF236D9163B6C274A9D47704BC496988460 +flush privileges; +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA ed25519 USING 'F4aF8bw7130VaRbdLCl4f/P/wkjDmgJXwWvpJ5gmsZc' OR unix_socket OR mysql_native_password USING '*7D8C3DF236D9163B6C274A9D47704BC496988460' +set password for mysqltest1 = password('foobar'); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA ed25519 USING 'qv2mG6HWCuy32Slb5xhV4THStewNz2VINVPbgk+XAJ8' OR unix_socket OR mysql_native_password USING '*7D8C3DF236D9163B6C274A9D47704BC496988460' +alter user mysqltest1 identified via unix_socket OR mysql_native_password as password("some"); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA unix_socket OR mysql_native_password USING '*BFE3F4604CFD21E6595080A261D92EF0183B5971' +set password for mysqltest1 = password('foobar'); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA unix_socket OR mysql_native_password USING '*9B500343BC52E2911172EB52AE5CF4847604C6E5' +alter user mysqltest1 identified via unix_socket; +set password for mysqltest1 = password('bla'); +ERROR HY000: SET PASSWORD is ignored for users authenticating via unix_socket plugin +alter user mysqltest1 identified via mysql_native_password as password("some") or unix_socket; +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA mysql_native_password USING '*BFE3F4604CFD21E6595080A261D92EF0183B5971' OR unix_socket +drop user mysqltest1; +create user mysqltest1 identified via ed25519 as password("good") OR unix_socket OR mysql_native_password as password("works"); +ERROR HY000: Column count of mysql.user is wrong. Expected 3, found 47. Created with MariaDB XX.YY.ZZ, now running XX.YY.ZZ. Please use mysql_upgrade to fix this error +create user USER identified via mysql_native_password as '1234567890123456789012345678901234567890a' OR unix_socket; +create user mysqltest1 identified via mysql_native_password as '1234567890123456789012345678901234567890a' OR unix_socket; +update mysql.global_priv set priv=replace(priv, '1234567890123456789012345678901234567890a', 'invalid password'); +flush privileges; +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA mysql_native_password USING 'invalid password' OR unix_socket +# name match = ok +select user(), current_user(), database(); +user() current_user() database() +USER@localhost USER@% test +# name does not match = failure +# SET PASSWORD helps +set password for mysqltest1 = password('bla'); +select user(), current_user(), database(); +user() current_user() database() +mysqltest1@localhost mysqltest1@% test +drop user USER, mysqltest1; +uninstall soname 'auth_socket'; +uninstall soname 'auth_ed25519'; diff --git a/mysql-test/suite/plugins/t/multiauth.test b/mysql-test/suite/plugins/t/multiauth.test new file mode 100644 index 00000000000..cb86b4ea2f0 --- /dev/null +++ b/mysql-test/suite/plugins/t/multiauth.test @@ -0,0 +1,179 @@ +# +# MDEV-11340 Allow multiple alternative authentication methods for the same user +# +--source include/have_unix_socket.inc +if (`SELECT '$USER' = 'mysqltest1'`) { + skip USER is mysqltest1; +} +if (!$AUTH_ED25519_SO) { + skip No auth_ed25519 plugin; +} + +--let $plugindir=`SELECT @@global.plugin_dir` +install soname 'auth_socket'; +install soname 'auth_ed25519'; + +--let $try_auth=$MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/peercred_test.txt + +--write_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt +--let $replace1=$USER@localhost +--let $replace2=$USER@% +--replace_result $replace1 "USER@localhost" $replace2 "USER@%" +select user(), current_user(), database(); +EOF + +--let $creplace=create user $USER +--let $dreplace=drop user $USER + +# +# socket,password +# +--replace_result $creplace "create user USER" +eval $creplace identified via unix_socket OR mysql_native_password as password("GOOD"); +create user mysqltest1 identified via unix_socket OR mysql_native_password as password("good"); +show create user mysqltest1; +--echo # name match = ok +--exec $try_auth -u $USER +--echo # name does not match, password good = ok +--exec $try_auth -u mysqltest1 -pgood +--echo # name does not match, password bad = failure +--error 1 +--exec $try_auth -u mysqltest1 -pbad +--replace_result $dreplace "drop user USER" +eval $dreplace, mysqltest1; + +# +# password,socket +# +--replace_result $creplace "create user USER" +eval $creplace identified via mysql_native_password as password("GOOD") OR unix_socket; +create user mysqltest1 identified via mysql_native_password as password("good") OR unix_socket; +show create user mysqltest1; +--echo # name match = ok +--exec $try_auth -u $USER +--echo # name does not match, password good = ok +--exec $try_auth -u mysqltest1 -pgood +--echo # name does not match, password bad = failure +--error 1 +--exec $try_auth -u mysqltest1 -pbad +--replace_result $dreplace "drop user USER" +eval $dreplace, mysqltest1; + +# +# socket,ed25519 +# +--replace_result $creplace "create user USER" +eval $creplace identified via unix_socket OR ed25519 as password("GOOD"); +create user mysqltest1 identified via unix_socket OR ed25519 as password("good"); +show create user mysqltest1; +--echo # name match = ok +--exec $try_auth -u $USER +--echo # name does not match, password good = ok +--exec $try_auth -u mysqltest1 -pgood +--echo # name does not match, password bad = failure +--error 1 +--exec $try_auth -u mysqltest1 -pbad +--replace_result $dreplace "drop user USER" +eval $dreplace, mysqltest1; + +# +# ed25519,socket +# +--replace_result $creplace "create user USER" +eval $creplace identified via ed25519 as password("GOOD") OR unix_socket; +create user mysqltest1 identified via ed25519 as password("good") OR unix_socket; +show create user mysqltest1; +--echo # name match = ok +--exec $try_auth -u $USER +--echo # name does not match, password good = ok +--exec $try_auth -u mysqltest1 -pgood +--echo # name does not match, password bad = failure +--error 1 +--exec $try_auth -u mysqltest1 -pbad +--replace_result $dreplace "drop user USER" +eval $dreplace, mysqltest1; + +# +# ed25519,socket,password +# +--replace_result $creplace "create user USER" +eval $creplace identified via ed25519 as password("GOOD") OR unix_socket OR mysql_native_password as password("works"); +create user mysqltest1 identified via ed25519 as password("good") OR unix_socket OR mysql_native_password as password("works"); +show create user mysqltest1; +--echo # name match = ok +--exec $try_auth -u $USER +--echo # name does not match, password good = ok +--exec $try_auth -u mysqltest1 -pgood +--echo # name does not match, second password works = ok +--exec $try_auth -u mysqltest1 -pworks +--echo # name does not match, password bad = failure +--error 1 +--exec $try_auth -u mysqltest1 -pbad +--replace_result $dreplace "drop user USER" +eval $dreplace, mysqltest1; + +# +# password,password +# +create user mysqltest1 identified via mysql_native_password as password("good") OR mysql_native_password as password("works"); +show create user mysqltest1; +--echo # password good = ok +--exec $try_auth -u mysqltest1 -pgood +--echo # second password works = ok +--exec $try_auth -u mysqltest1 -pworks +--echo # password bad = failure +--error 1 +--exec $try_auth -u mysqltest1 -pbad +drop user mysqltest1; + +# +# show grants, flush privileges, set password, alter user +# +create user mysqltest1 identified via ed25519 as password("good") OR unix_socket OR mysql_native_password as password("works"); +show grants for mysqltest1; +select json_detailed(priv) from mysql.global_priv where user='mysqltest1'; +select password,plugin,authentication_string from mysql.user where user='mysqltest1'; +flush privileges; +show create user mysqltest1; +set password for mysqltest1 = password('foobar'); +show create user mysqltest1; +alter user mysqltest1 identified via unix_socket OR mysql_native_password as password("some"); +show create user mysqltest1; +set password for mysqltest1 = password('foobar'); +show create user mysqltest1; +alter user mysqltest1 identified via unix_socket; +--error ER_SET_PASSWORD_AUTH_PLUGIN +set password for mysqltest1 = password('bla'); +alter user mysqltest1 identified via mysql_native_password as password("some") or unix_socket; +show create user mysqltest1; +drop user mysqltest1; + +--source include/switch_to_mysql_user.inc +--replace_regex /\d{6}/XX.YY.ZZ/ +--error ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE +create user mysqltest1 identified via ed25519 as password("good") OR unix_socket OR mysql_native_password as password("works"); +--source include/switch_to_mysql_global_priv.inc + +# +# invalid password,socket +# +--replace_result $creplace "create user USER" +eval $creplace identified via mysql_native_password as '1234567890123456789012345678901234567890a' OR unix_socket; +create user mysqltest1 identified via mysql_native_password as '1234567890123456789012345678901234567890a' OR unix_socket; +update mysql.global_priv set priv=replace(priv, '1234567890123456789012345678901234567890a', 'invalid password'); +flush privileges; +show create user mysqltest1; +--echo # name match = ok +--exec $try_auth -u $USER +--echo # name does not match = failure +--error 1 +--exec $try_auth -u mysqltest1 +--echo # SET PASSWORD helps +set password for mysqltest1 = password('bla'); +--exec $try_auth -u mysqltest1 -pbla +--replace_result $dreplace "drop user USER" +eval $dreplace, mysqltest1; + +uninstall soname 'auth_socket'; +uninstall soname 'auth_ed25519'; +--remove_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt diff --git a/plugin/auth_gssapi/mysql-test/auth_gssapi/multiauth.result b/plugin/auth_gssapi/mysql-test/auth_gssapi/multiauth.result new file mode 100644 index 00000000000..c65eb7a8634 --- /dev/null +++ b/plugin/auth_gssapi/mysql-test/auth_gssapi/multiauth.result @@ -0,0 +1,34 @@ +INSTALL SONAME 'auth_gssapi'; +Warnings: +Note 1105 SSPI: using principal name 'localhost', mech 'Negotiate' +CREATE USER 'nosuchuser' IDENTIFIED WITH gssapi OR mysql_native_password as password("good"); +connect(localhost,nosuchuser,,test,MASTER_MYPORT,MASTER_MYSOCK); +connect con1,localhost,nosuchuser,,; +ERROR 28000: Access denied for user 'nosuchuser'@'localhost' (using password: NO) +connect con1,localhost,nosuchuser,good,; +SELECT USER(),CURRENT_USER(); +USER() CURRENT_USER() +nosuchuser@localhost nosuchuser@% +disconnect con1; +connection default; +DROP USER nosuchuser; +CREATE USER 'nosuchuser' IDENTIFIED WITH mysql_native_password as password("good") OR gssapi; +connect(localhost,nosuchuser,,test,MASTER_MYPORT,MASTER_MYSOCK); +connect con1,localhost,nosuchuser,,; +ERROR 28000: GSSAPI name mismatch, requested 'nosuchuser', actual name 'GSSAPI_SHORTNAME' +connect con1,localhost,nosuchuser,good,; +SELECT USER(),CURRENT_USER(); +USER() CURRENT_USER() +nosuchuser@localhost nosuchuser@% +disconnect con1; +connection default; +DROP USER nosuchuser; +CREATE USER 'GSSAPI_SHORTNAME' IDENTIFIED WITH mysql_native_password as password("good") OR gssapi; +connect con1,localhost,$GSSAPI_SHORTNAME,,; +SELECT USER(),CURRENT_USER(); +USER() CURRENT_USER() +GSSAPI_SHORTNAME@localhost GSSAPI_SHORTNAME@% +disconnect con1; +connection default; +DROP USER 'GSSAPI_SHORTNAME'; +UNINSTALL SONAME 'auth_gssapi'; diff --git a/plugin/auth_gssapi/mysql-test/auth_gssapi/multiauth.test b/plugin/auth_gssapi/mysql-test/auth_gssapi/multiauth.test new file mode 100644 index 00000000000..10e1e80907e --- /dev/null +++ b/plugin/auth_gssapi/mysql-test/auth_gssapi/multiauth.test @@ -0,0 +1,36 @@ +--replace_regex /name '[^']+'/name 'localhost'/ +INSTALL SONAME 'auth_gssapi'; + +# gssapi,password +CREATE USER 'nosuchuser' IDENTIFIED WITH gssapi OR mysql_native_password as password("good"); +replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT; +error ER_ACCESS_DENIED_ERROR; +connect (con1,localhost,nosuchuser,,); +connect (con1,localhost,nosuchuser,good,); +SELECT USER(),CURRENT_USER(); +disconnect con1; +connection default; +DROP USER nosuchuser; + +# password,gssapi +CREATE USER 'nosuchuser' IDENTIFIED WITH mysql_native_password as password("good") OR gssapi; +replace_result $MASTER_MYSOCK MASTER_MYSOCK $MASTER_MYPORT MASTER_MYPORT $GSSAPI_SHORTNAME GSSAPI_SHORTNAME; +error ER_ACCESS_DENIED_ERROR; +connect (con1,localhost,nosuchuser,,); +connect (con1,localhost,nosuchuser,good,); +SELECT USER(),CURRENT_USER(); +disconnect con1; +connection default; +DROP USER nosuchuser; + +replace_result $GSSAPI_SHORTNAME GSSAPI_SHORTNAME; +eval CREATE USER '$GSSAPI_SHORTNAME' IDENTIFIED WITH mysql_native_password as password("good") OR gssapi; +connect (con1,localhost,$GSSAPI_SHORTNAME,,); +replace_result $GSSAPI_SHORTNAME GSSAPI_SHORTNAME; +SELECT USER(),CURRENT_USER(); +disconnect con1; +connection default; +replace_result $GSSAPI_SHORTNAME GSSAPI_SHORTNAME; +eval DROP USER '$GSSAPI_SHORTNAME'; + +UNINSTALL SONAME 'auth_gssapi'; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index aa7b08092b5..ad9e2b446ed 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2018, Oracle and/or its affiliates. - Copyright (c) 2009, 2018, MariaDB + Copyright (c) 2009, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -149,29 +149,41 @@ public: enum SSL_type ssl_type; uint password_errors; const char *ssl_cipher, *x509_issuer, *x509_subject; - LEX_CSTRING plugin; - LEX_CSTRING auth_string; LEX_CSTRING default_rolename; - LEX_CSTRING salt; + struct AUTH { LEX_CSTRING plugin, auth_string, salt; } *auth; + uint nauth; + + bool alloc_auth(MEM_ROOT *root, uint n) + { + return !(auth= (AUTH*) alloc_root(root, (nauth= n)*sizeof(AUTH))); + } ACL_USER *copy(MEM_ROOT *root) { - ACL_USER *dst= (ACL_USER *) alloc_root(root, sizeof(ACL_USER)); - if (!dst) + ACL_USER *dst; + AUTH *dauth; + if (!multi_alloc_root(root, &dst, sizeof(ACL_USER), + &dauth, sizeof(AUTH)*nauth, NULL)) return 0; *dst= *this; dst->user= safe_lexcstrdup_root(root, user); dst->ssl_cipher= safe_strdup_root(root, ssl_cipher); dst->x509_issuer= safe_strdup_root(root, x509_issuer); dst->x509_subject= safe_strdup_root(root, x509_subject); - if (plugin.str == native_password_plugin_name.str || - plugin.str == old_password_plugin_name.str) - dst->plugin= plugin; - else - dst->plugin= safe_lexcstrdup_root(root, plugin); - dst->auth_string= safe_lexcstrdup_root(root, auth_string); - if (salt.str) - dst->salt= safe_lexcstrdup_root(root, salt); + dst->auth= dauth; + for (uint i=0; i < nauth; i++, dauth++) + { + if (auth[i].plugin.str == native_password_plugin_name.str || + auth[i].plugin.str == old_password_plugin_name.str) + dauth->plugin= auth[i].plugin; + else + dauth->plugin= safe_lexcstrdup_root(root, auth[i].plugin); + dauth->auth_string= safe_lexcstrdup_root(root, auth[i].auth_string); + if (auth[i].salt.length == 0) + dauth->salt= auth[i].salt; + else + dauth->salt= safe_lexcstrdup_root(root, auth[i].salt); + } dst->host.hostname= safe_strdup_root(root, host.hostname); dst->default_rolename= safe_lexcstrdup_root(root, default_rolename); bzero(&dst->role_grants, sizeof(role_grants)); @@ -244,7 +256,6 @@ ulong role_global_merges= 0, role_db_merges= 0, role_table_merges= 0, #endif #ifndef NO_EMBEDDED_ACCESS_CHECKS -static bool fix_and_copy_user(LEX_USER *to, LEX_USER *from, THD *thd); static void update_hostname(acl_host_and_ip *host, const char *hostname); static ulong get_sort(uint count,...); static bool show_proxy_grants (THD *, const char *, const char *, @@ -817,8 +828,8 @@ class User_table: public Grant_table_base } virtual LEX_CSTRING& name() const = 0; - virtual int get_auth(THD *, MEM_ROOT *, const char **, const char **) const= 0; - virtual void set_auth(const char *, size_t, const char *, size_t) const = 0; + virtual int get_auth(THD *, MEM_ROOT *, ACL_USER *u) const= 0; + virtual bool set_auth(const ACL_USER &u) const = 0; virtual ulong get_access() const = 0; virtual void set_access(ulong rights, bool revoke) const = 0; @@ -867,54 +878,67 @@ class User_table_tabular: public User_table LEX_CSTRING& name() const { return MYSQL_TABLE_NAME_USER; } - int get_auth(THD *thd, MEM_ROOT *root, const char **plugin, const char **authstr) const + int get_auth(THD *thd, MEM_ROOT *root, ACL_USER *u) const { + u->alloc_auth(root, 1); if (have_password()) { - *authstr= safe_str(::get_field(&acl_memroot, password())); - *plugin= guess_auth_plugin(thd, strlen(*authstr)).str; + const char *as= safe_str(::get_field(&acl_memroot, password())); + u->auth->auth_string.str= as; + u->auth->auth_string.length= strlen(as); + u->auth->plugin= guess_auth_plugin(thd, u->auth->auth_string.length); } else { - *plugin= native_password_plugin_name.str; - *authstr= ""; + u->auth->plugin= native_password_plugin_name; + u->auth->auth_string= empty_clex_str; } - if (this->plugin() && this->authstr()) + if (plugin() && authstr()) { - char *tmpstr= ::get_field(&acl_memroot, this->plugin()); + char *tmpstr= ::get_field(&acl_memroot, plugin()); if (tmpstr) { - const char *passw= *authstr; - *plugin= tmpstr; - *authstr= safe_str(::get_field(&acl_memroot, this->authstr())); - - if (*passw) + const char *pw= u->auth->auth_string.str; + const char *as= safe_str(::get_field(&acl_memroot, authstr())); + if (*pw) { - if (**authstr && strcmp(*authstr, passw)) + if (*as && strcmp(as, pw)) { sql_print_warning("'user' entry '%s@%s' has both a password and an " "authentication plugin specified. The password will be ignored.", safe_str(get_user(thd->mem_root)), safe_str(get_host(thd->mem_root))); } else - *authstr= passw; + as= pw; } + u->auth->plugin.str= tmpstr; + u->auth->plugin.length= strlen(tmpstr); + u->auth->auth_string.str= as; + u->auth->auth_string.length= strlen(as); } } return 0; } - void set_auth(const char *p, size_t pl, const char *as, size_t asl) const + bool set_auth(const ACL_USER &u) const { + if (u.nauth != 1) + return 1; if (plugin()) { if (have_password()) password()->reset(); - plugin()->store(p, pl, system_charset_info); - authstr()->store(as, asl, system_charset_info); + plugin()->store(u.auth->plugin.str, u.auth->plugin.length, system_charset_info); + authstr()->store(u.auth->auth_string.str, u.auth->auth_string.length, system_charset_info); } else - password()->store(as, asl, system_charset_info); + { + if (u.auth->plugin.str != native_password_plugin_name.str && + u.auth->plugin.str != old_password_plugin_name.str) + return 1; + password()->store(u.auth->auth_string.str, u.auth->auth_string.length, system_charset_info); + } + return 0; } ulong get_access() const @@ -1202,18 +1226,130 @@ class User_table_json: public User_table { LEX_CSTRING& name() const { return MYSQL_TABLE_NAME[USER_TABLE]; } - int get_auth(THD *thd, MEM_ROOT *root, const char **plugin, const char **authstr) const + int get_auth(THD *thd, MEM_ROOT *root, ACL_USER *u) const { - *plugin= get_str_value(root, "plugin"); - if (!**plugin) - *plugin= native_password_plugin_name.str; - *authstr= get_str_value(root, "authentication_string"); - return *plugin == NULL || *authstr == NULL; + size_t array_len; + const char *array; + int vl; + const char *v; + + if (get_value("auth_or", JSV_ARRAY, &array, &array_len)) + { + u->alloc_auth(root, 1); + return get_auth1(thd, root, u, 0); + } + + if (json_get_array_item(array, array + array_len, (int)array_len, + &v, &vl) != JSV_NOTHING) + return 1; + u->alloc_auth(root, vl); + for (uint i=0; i < u->nauth; i++) + { + if (json_get_array_item(array, array + array_len, i, &v, &vl) != JSV_OBJECT) + return 1; + + const char *p, *a; + int pl, al; + switch (json_get_object_key(v, v + vl, "plugin", &p, &pl)) { + case JSV_STRING: u->auth[i].plugin.str= strmake_root(root, p, pl); + u->auth[i].plugin.length= pl; + break; + case JSV_NOTHING: if (get_auth1(thd, root, u, i)) + return 1; + else + continue; + default: return 1; + } + switch (json_get_object_key(v, v + vl, "authentication_string", &a, &al)) { + case JSV_NOTHING: u->auth[i].auth_string= empty_clex_str; + break; + case JSV_STRING: u->auth[i].auth_string.str= strmake_root(root, a, al); + u->auth[i].auth_string.length= al; + break; + default: return 1; + } + } + return 0; } - void set_auth(const char *p, size_t pl, const char *as, size_t asl) const + + int get_auth1(THD *thd, MEM_ROOT *root, ACL_USER *u, uint n) const { - set_str_value("plugin", p, pl); - set_str_value("authentication_string", as, asl); + const char *authstr= get_str_value(root, "authentication_string"); + const char *plugin= get_str_value(root, "plugin"); + if (plugin && authstr) + { + if (plugin && *plugin) + { + u->auth[n].plugin.str= plugin; + u->auth[n].plugin.length= strlen(plugin); + } + else + u->auth[n].plugin= native_password_plugin_name; + u->auth[n].auth_string.str= authstr; + u->auth[n].auth_string.length= strlen(authstr); + return 0; + } + return 1; + } + + bool append_str_value(String *to, const LEX_CSTRING &str) const + { + to->append('"'); + to->reserve(str.length*2); + int len= json_escape(system_charset_info, (uchar*)str.str, (uchar*)str.str + str.length, + to->charset(), (uchar*)to->end(), (uchar*)to->end() + str.length*2); + if (len < 0) + return 1; + to->length(to->length() + len); + to->append('"'); + return 0; + } + + bool set_auth(const ACL_USER &u) const + { + StringBuffer json(m_table->field[2]->charset()); + if (u.nauth == 1) + return set_auth1(u, 0); + bool top_done = false; + json.append('['); + for (uint i=0; i < u.nauth; i++) + { + ACL_USER::AUTH * const auth= u.auth + i; + if (i) + json.append(','); + json.append('{'); + if (!top_done && + (auth->plugin.str == native_password_plugin_name.str || + auth->plugin.str == old_password_plugin_name.str || + i == u.nauth - 1)) + { + if (set_auth1(u, i)) + return 1; + top_done= true; + } + else + { + json.append(STRING_WITH_LEN("\"plugin\":")); + if (append_str_value(&json, auth->plugin)) + return 1; + if (auth->auth_string.length) + { + json.append(STRING_WITH_LEN(",\"authentication_string\":")); + if (append_str_value(&json, auth->auth_string)) + return 1; + } + } + json.append('}'); + } + json.append(']'); + return set_value("auth_or", json.ptr(), json.length(), false) == JSV_BAD_JSON; + } + bool set_auth1(const ACL_USER &u, uint i) const + { + return set_str_value("plugin", + u.auth[i].plugin.str, u.auth[i].plugin.length) || + set_str_value("authentication_string", + u.auth[i].auth_string.str, u.auth[i].auth_string.length); } ulong get_access() const { @@ -1349,8 +1485,8 @@ class User_table_json: public User_table return false; return true; } - bool set_value(const char *key, - const char *val, size_t vlen, bool string) const + enum json_types set_value(const char *key, + const char *val, size_t vlen, bool string) const { int value_len; const char *value_start; @@ -1361,7 +1497,7 @@ class User_table_json: public User_table value_type= json_get_object_key(res->ptr(), res->end(), key, &value_start, &value_len); if (value_type == JSV_BAD_JSON) - return 1; // invalid + return value_type; // invalid StringBuffer json(res->charset()); json.copy(res->ptr(), value_start - res->ptr(), res->charset()); if (value_type == JSV_NOTHING) @@ -1382,7 +1518,7 @@ class User_table_json: public User_table json.append(value_start, res->end() - value_start); DBUG_ASSERT(json_valid(json.ptr(), json.length(), json.charset())); m_table->field[2]->store(json.ptr(), json.length(), json.charset()); - return 0; + return value_type; } bool set_str_value(const char *key, const char *val, size_t vlen) const { @@ -1393,22 +1529,24 @@ class User_table_json: public User_table (uchar*)buf, (uchar*)buf+sizeof(buf)); if (blen < 0) return 1; - return set_value(key, buf, blen, true); + return set_value(key, buf, blen, true) == JSV_BAD_JSON; } bool set_int_value(const char *key, longlong val) const { char v[MY_INT64_NUM_DECIMAL_DIGITS+1]; size_t vlen= longlong10_to_str(val, v, -10) - v; - return set_value(key, v, vlen, false); + return set_value(key, v, vlen, false) == JSV_BAD_JSON; } bool set_double_value(const char *key, double val) const { char v[FLOATING_POINT_BUFFER+1]; size_t vlen= my_fcvt(val, TIME_SECOND_PART_DIGITS, v, NULL); - return set_value(key, v, vlen, false); + return set_value(key, v, vlen, false) == JSV_BAD_JSON; } bool set_bool_value(const char *key, bool val) const - { return set_value(key, val ? "true" : "false", val ? 4 : 5, false); } + { + return set_value(key, val ? "true" : "false", val ? 4 : 5, false) == JSV_BAD_JSON; + } }; class Db_table: public Grant_table_base @@ -1781,22 +1919,22 @@ static bool validate_password(THD *thd, const LEX_CSTRING &user, return false; } -static int set_user_salt(ACL_USER *acl_user, plugin_ref plugin) +static int set_user_salt(ACL_USER::AUTH *auth, plugin_ref plugin) { - st_mysql_auth *auth= (st_mysql_auth *) plugin_decl(plugin)->info; - if (auth->interface_version >= 0x0202 && acl_user->auth_string.length && - auth->preprocess_hash) + st_mysql_auth *info= (st_mysql_auth *) plugin_decl(plugin)->info; + if (info->interface_version >= 0x0202 && info->preprocess_hash && + auth->auth_string.length) { uchar buf[MAX_SCRAMBLE_LENGTH]; size_t len= sizeof(buf); - if (auth->preprocess_hash(acl_user->auth_string.str, - acl_user->auth_string.length, buf, &len)) + if (info->preprocess_hash(auth->auth_string.str, + auth->auth_string.length, buf, &len)) return 1; - acl_user->salt.str= (char*)memdup_root(&acl_memroot, buf, len); - acl_user->salt.length= len; + auth->salt.str= (char*)memdup_root(&acl_memroot, buf, len); + auth->salt.length= len; } else - acl_user->salt= acl_user->auth_string; + auth->salt= auth->auth_string; return 0; } @@ -1808,13 +1946,14 @@ static int set_user_salt(ACL_USER *acl_user, plugin_ref plugin) converts auth_string to salt. Fails if the plain-text password fails validation, if the plugin is - not loaded, if the auth_string is invalid. + not loaded, if the auth_string is invalid, if the password is not applicable */ -static int set_user_auth(THD *thd, ACL_USER *acl_user, const LEX_CSTRING &pwtext) +static int set_user_auth(THD *thd, const LEX_CSTRING &user, + ACL_USER::AUTH *auth, const LEX_CSTRING &pwtext) { - const char *plugin_name= acl_user->plugin.str; + const char *plugin_name= auth->plugin.str; bool unlock_plugin= false; - plugin_ref plugin= get_auth_plugin(thd, acl_user->plugin, &unlock_plugin); + plugin_ref plugin= get_auth_plugin(thd, auth->plugin, &unlock_plugin); int res= 1; if (!plugin) @@ -1822,40 +1961,49 @@ static int set_user_auth(THD *thd, ACL_USER *acl_user, const LEX_CSTRING &pwtext push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_PLUGIN_IS_NOT_LOADED, ER_THD(thd, ER_PLUGIN_IS_NOT_LOADED), plugin_name); - return res; + return ER_PLUGIN_IS_NOT_LOADED; } - acl_user->salt= acl_user->auth_string; + auth->salt= auth->auth_string; - st_mysql_auth *auth= (st_mysql_auth *) plugin_decl(plugin)->info; - if (auth->interface_version >= 0x0202) + st_mysql_auth *info= (st_mysql_auth *) plugin_decl(plugin)->info; + if (info->interface_version < 0x0202) { - if (auth->hash_password && - validate_password(thd, acl_user->user, pwtext, - acl_user->auth_string.length)) - goto end; - if (pwtext.length) + res= pwtext.length ? ER_SET_PASSWORD_AUTH_PLUGIN : 0; + goto end; + } + + if (info->hash_password && + validate_password(thd, user, pwtext, auth->auth_string.length)) + { + res= ER_NOT_VALID_PASSWORD; + goto end; + } + if (pwtext.length) + { + if (info->hash_password) { - if (auth->hash_password) + char buf[MAX_SCRAMBLE_LENGTH]; + size_t len= sizeof(buf) - 1; + if (info->hash_password(pwtext.str, pwtext.length, buf, &len)) { - char buf[MAX_SCRAMBLE_LENGTH]; - size_t len= sizeof(buf) - 1; - if (auth->hash_password(pwtext.str, pwtext.length, buf, &len)) - goto end; // OOM? - buf[len] = 0; - acl_user->auth_string.str= (char*)memdup_root(&acl_memroot, buf, len+1); - acl_user->auth_string.length= len; - } - else - { - push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, - ER_SET_PASSWORD_AUTH_PLUGIN, - ER_THD(thd, ER_SET_PASSWORD_AUTH_PLUGIN), - acl_user->plugin.str); + res= ER_OUTOFMEMORY; + goto end; } + buf[len] = 0; + auth->auth_string.str= (char*)memdup_root(&acl_memroot, buf, len+1); + auth->auth_string.length= len; } - if (set_user_salt(acl_user, plugin)) + else + { + res= ER_SET_PASSWORD_AUTH_PLUGIN; goto end; + } + } + if (set_user_salt(auth, plugin)) + { + res= ER_PASSWD_LENGTH; + goto end; } res= 0; @@ -1869,25 +2017,30 @@ end: /** Lazily computes user's salt from the password hash */ -static bool set_user_salt_if_needed(ACL_USER *user_copy, plugin_ref plugin) +static bool set_user_salt_if_needed(ACL_USER *user_copy, int curr_auth, + plugin_ref plugin) { - DBUG_ASSERT(!strcasecmp(user_copy->plugin.str, plugin_name(plugin)->str)); + ACL_USER::AUTH *auth_copy= user_copy->auth + curr_auth; + DBUG_ASSERT(!strcasecmp(auth_copy->plugin.str, plugin_name(plugin)->str)); - if (user_copy->salt.str) + if (auth_copy->salt.str) return 0; // already done - if (set_user_salt(user_copy, plugin)) + if (set_user_salt(auth_copy, plugin)) return 1; mysql_mutex_lock(&acl_cache->lock); ACL_USER *user= find_user_exact(user_copy->host.hostname, user_copy->user.str); // make sure the user wasn't altered or dropped meanwhile - if (user && !user->salt.str && - user->plugin.length == user_copy->plugin.length && - user->auth_string.length == user_copy->auth_string.length && - !memcmp(user->plugin.str, user_copy->plugin.str, user->plugin.length) && - !memcmp(user->auth_string.str, user_copy->auth_string.str, user->auth_string.length)) - user->salt= user_copy->salt; + if (user) + { + ACL_USER::AUTH *auth= user->auth + curr_auth; + if (!auth->salt.str && auth->plugin.length == auth_copy->plugin.length && + auth->auth_string.length == auth_copy->auth_string.length && + !memcmp(auth->plugin.str, auth_copy->plugin.str, auth->plugin.length) && + !memcmp(auth->auth_string.str, auth_copy->auth_string.str, auth->auth_string.length)) + auth->salt= auth_copy->salt; + } mysql_mutex_unlock(&acl_cache->lock); return 0; } @@ -1904,13 +2057,13 @@ static bool set_user_salt_if_needed(ACL_USER *user_copy, plugin_ref plugin) @retval 0 the pointers were fixed @retval 1 this ACL_USER uses a not built-in plugin */ -static bool fix_user_plugin_ptr(ACL_USER *user) +static bool fix_user_plugin_ptr(ACL_USER::AUTH *auth) { - if (lex_string_eq(&user->plugin, &native_password_plugin_name)) - user->plugin= native_password_plugin_name; + if (lex_string_eq(&auth->plugin, &native_password_plugin_name)) + auth->plugin= native_password_plugin_name; else - if (lex_string_eq(&user->plugin, &old_password_plugin_name)) - user->plugin= old_password_plugin_name; + if (lex_string_eq(&auth->plugin, &old_password_plugin_name)) + auth->plugin= old_password_plugin_name; else return true; return false; @@ -2133,12 +2286,14 @@ static bool acl_load(THD *thd, const Grant_tables& tables) continue; } - if (user_table.get_auth(thd, &acl_memroot, - &user.plugin.str, &user.auth_string.str)) + if (user_table.get_auth(thd, &acl_memroot, &user)) continue; - user.plugin.length= strlen(user.plugin.str); - user.auth_string.length= strlen(user.auth_string.str); - fix_user_plugin_ptr(&user); + for (uint i= 0; i < user.nauth; i++) + { + ACL_USER::AUTH *auth= user.auth + i; + auth->salt= null_clex_str; + fix_user_plugin_ptr(auth); + } user.ssl_type= user_table.get_ssl_type(); user.ssl_cipher= user_table.get_ssl_cipher(&acl_memroot); @@ -2858,11 +3013,12 @@ static void acl_update_role(const char *rolename, ulong privileges) } -static int acl_user_update(THD *thd, ACL_USER *acl_user, const ACL_USER *from, - const LEX_USER &combo, enum SSL_type ssl_type, - const char *ssl_cipher, const char *x509_issuer, - const char *x509_subject, const USER_RESOURCES *mqh, - ulong privileges) +static int acl_user_update(THD *thd, ACL_USER *acl_user, uint nauth, + const ACL_USER *from, const LEX_USER &combo, + const enum SSL_type ssl_type, + const char *ssl_cipher, const char *x509_issuer, + const char *x509_subject, const USER_RESOURCES *mqh, + const ulong privileges) { if (from) *acl_user= *from; @@ -2873,21 +3029,29 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, const ACL_USER *from, update_hostname(&acl_user->host, safe_strdup_root(&acl_memroot, combo.host.str)); acl_user->hostname_length= combo.host.length; acl_user->sort= get_sort(2, acl_user->host.hostname, acl_user->user.str); - acl_user->plugin= native_password_plugin_name; - acl_user->auth_string= empty_clex_str; my_init_dynamic_array(&acl_user->role_grants, sizeof(ACL_USER *), 0, 8, MYF(0)); } - if (combo.plugin.length) + if (nauth) { - acl_user->plugin= combo.plugin; - acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, combo.auth); - if (fix_user_plugin_ptr(acl_user)) - acl_user->plugin= safe_lexcstrdup_root(&acl_memroot, combo.plugin); - if (set_user_auth(thd, acl_user, combo.pwtext)) - return 1; + if (acl_user->nauth >= nauth) + acl_user->nauth= nauth; + else + acl_user->alloc_auth(&acl_memroot, nauth); + + USER_AUTH *auth= combo.auth; + for (uint i= 0; i < nauth; i++, auth= auth->next) + { + acl_user->auth[i].plugin= auth->plugin; + acl_user->auth[i].auth_string= safe_lexcstrdup_root(&acl_memroot, auth->auth_str); + if (fix_user_plugin_ptr(acl_user->auth + i)) + acl_user->auth[i].plugin= safe_lexcstrdup_root(&acl_memroot, auth->plugin); + if (set_user_auth(thd, acl_user->user, acl_user->auth + i, auth->pwtext)) + return 1; + } } + acl_user->access= privileges; if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) acl_user->user_resource.questions= mqh->questions; @@ -3382,12 +3546,8 @@ end: bool check_change_password(THD *thd, LEX_USER *user) { LEX_USER *real_user= get_current_user(thd, user); - - if (fix_and_copy_user(real_user, user, thd)) - return true; - - *user= *real_user; - + user->user= real_user->user; + user->host= real_user->host; return check_alter_user(thd, user->host.str, user->user.str); } @@ -3410,10 +3570,13 @@ bool change_password(THD *thd, LEX_USER *user) ulong query_length= 0; enum_binlog_format save_binlog_format; int result=0; + ACL_USER *acl_user; + ACL_USER::AUTH auth; + const char *password_plugin= 0; const CSET_STRING query_save __attribute__((unused)) = thd->query_string; DBUG_ENTER("change_password"); DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", - user->host.str, user->user.str, user->auth.str)); + user->host.str, user->user.str, user->auth->auth_str.str)); DBUG_ASSERT(user->host.str != 0); // Ensured by caller /* @@ -3432,50 +3595,62 @@ bool change_password(THD *thd, LEX_USER *user) DBUG_RETURN(result != 1); result= 1; - mysql_mutex_lock(&acl_cache->lock); - ACL_USER *acl_user; + if (!(acl_user= find_user_exact(user->host.str, user->user.str))) { - mysql_mutex_unlock(&acl_cache->lock); - my_message(ER_PASSWORD_NO_MATCH, - ER_THD(thd, ER_PASSWORD_NO_MATCH), MYF(0)); + my_error(ER_PASSWORD_NO_MATCH, MYF(0)); goto end; } - if (acl_user->plugin.str == native_password_plugin_name.str || - acl_user->plugin.str == old_password_plugin_name.str) + if (acl_user->nauth == 1 && + (acl_user->auth[0].plugin.str == native_password_plugin_name.str || + acl_user->auth[0].plugin.str == old_password_plugin_name.str)) { /* historical hack of auto-changing the plugin */ - acl_user->plugin= guess_auth_plugin(thd, user->auth.length); + acl_user->auth[0].plugin= guess_auth_plugin(thd, user->auth->auth_str.length); } - acl_user->auth_string= safe_lexcstrdup_root(&acl_memroot, user->auth); - if (set_user_auth(thd, acl_user, user->pwtext)) + for (uint i=0; i < acl_user->nauth; i++) { - mysql_mutex_unlock(&acl_cache->lock); + auth= acl_user->auth[i]; + auth.auth_string= safe_lexcstrdup_root(&acl_memroot, user->auth->auth_str); + int r= set_user_auth(thd, user->user, &auth, user->auth->pwtext); + if (r == ER_SET_PASSWORD_AUTH_PLUGIN) + password_plugin= auth.plugin.str; + else if (r) + goto end; + else + { + acl_user->auth[i]= auth; + password_plugin= 0; + break; + } + } + if (password_plugin) + { + my_error(ER_SET_PASSWORD_AUTH_PLUGIN, MYF(0), password_plugin); goto end; } if (update_user_table_password(thd, tables.user_table(), *acl_user)) - { - mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */ goto end; - } - acl_cache->clear(1); // Clear locked hostname cache + acl_cache->clear(1); // Clear locked hostname cache mysql_mutex_unlock(&acl_cache->lock); result= 0; if (mysql_bin_log.is_open()) { query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'", - user->user.str, safe_str(user->host.str), acl_user->auth_string.str); + user->user.str, safe_str(user->host.str), auth.auth_string.str); DBUG_ASSERT(query_length); thd->clear_error(); result= thd->binlog_query(THD::STMT_QUERY_TYPE, buff, query_length, FALSE, FALSE, FALSE, 0); } end: + if (result) + mysql_mutex_unlock(&acl_cache->lock); close_mysql_tables(thd); #ifdef WITH_WSREP @@ -3920,19 +4095,24 @@ static bool update_user_table_password(THD *thd, const User_table& user_table, HA_READ_KEY_EXACT)) { my_message(ER_PASSWORD_NO_MATCH, ER_THD(thd, ER_PASSWORD_NO_MATCH), - MYF(0)); /* purecov: deadcode */ - DBUG_RETURN(1); /* purecov: deadcode */ + MYF(0)); + DBUG_RETURN(1); } - store_record(table,record[1]); + store_record(table, record[1]); - user_table.set_auth(user.plugin.str, user.plugin.length, - user.auth_string.str, user.auth_string.length); + if (user_table.set_auth(user)) + { + my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), + user_table.name().str, 3, user_table.num_fields(), + static_cast(table->s->mysql_version), MYSQL_VERSION_ID); + DBUG_RETURN(1); + } if (unlikely(error= table->file->ha_update_row(table->record[1], table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) { - table->file->print_error(error,MYF(0)); /* purecov: deadcode */ + table->file->print_error(error,MYF(0)); DBUG_RETURN(1); } DBUG_RETURN(0); @@ -3977,6 +4157,7 @@ static bool test_if_create_new_users(THD *thd) /**************************************************************************** Handle GRANT commands ****************************************************************************/ +static USER_AUTH auth_no_password; static int replace_user_table(THD *thd, const User_table &user_table, LEX_USER * const combo, ulong rights, @@ -3984,6 +4165,7 @@ static int replace_user_table(THD *thd, const User_table &user_table, const bool no_auto_create) { int error = -1; + uint nauth= 0; bool old_row_exists=0; uchar user_key[MAX_KEY_LENGTH]; bool handle_as_role= combo->is_role(); @@ -4021,8 +4203,7 @@ static int replace_user_table(THD *thd, const User_table &user_table, see also test_if_create_new_users() */ - else if (!combo->auth.length && !combo->plugin.length && - !combo->pwtext.length && no_auto_create) + else if (!combo->has_auth() && no_auto_create) { my_error(ER_PASSWORD_NO_MATCH, MYF(0)); goto end; @@ -4032,18 +4213,9 @@ static int replace_user_table(THD *thd, const User_table &user_table, my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0)); goto end; } - else if (combo->plugin.length) - { - if (!plugin_is_ready(&combo->plugin, MYSQL_AUTHENTICATION_PLUGIN)) - { - my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), combo->plugin.str); - goto end; - } - } - else /* combo->plugin.length == 0 */ - { - combo->plugin= guess_auth_plugin(thd, combo->auth.length); - } + + if (!combo->auth) + combo->auth= &auth_no_password; old_row_exists = 0; restore_record(table,s->default_values); @@ -4054,15 +4226,24 @@ static int replace_user_table(THD *thd, const User_table &user_table, { old_row_exists = 1; store_record(table,record[1]); // Save copy for update - if (!combo->plugin.length && (combo->auth.length || combo->pwtext.length)) + } + + for (USER_AUTH *auth= combo->auth; auth; auth= auth->next) + { + nauth++; + if (auth->plugin.length) { - /* GRANT ... IDENTIFIED BY */ - combo->plugin= guess_auth_plugin(thd, combo->auth.length); + if (!plugin_is_ready(&auth->plugin, MYSQL_AUTHENTICATION_PLUGIN)) + { + my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), auth->plugin.str); + goto end; + } } + else + auth->plugin= guess_auth_plugin(thd, auth->auth_str.length); } /* Update table columns with new privileges */ - user_table.set_access(rights, revoke_grant); rights= user_table.get_access(); @@ -4089,15 +4270,20 @@ static int replace_user_table(THD *thd, const User_table &user_table, my_error(ER_PASSWORD_NO_MATCH, MYF(0)); goto end; } - if (acl_user_update(thd, &new_acl_user, + if (acl_user_update(thd, &new_acl_user, nauth, old_row_exists ? old_acl_user : NULL, *combo, lex->ssl_type, lex->ssl_cipher, lex->x509_issuer, lex->x509_subject, &lex->mqh, rights)) goto end; - user_table.set_auth(new_acl_user.plugin.str, new_acl_user.plugin.length, - new_acl_user.auth_string.str, new_acl_user.auth_string.length); + if (user_table.set_auth(new_acl_user)) + { + my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), + user_table.name().str, 3, user_table.num_fields(), + static_cast(table->s->mysql_version), MYSQL_VERSION_ID); + DBUG_RETURN(1); + } switch (lex->ssl_type) { case SSL_TYPE_NOT_SPECIFIED: @@ -6325,28 +6511,14 @@ static bool merge_one_role_privileges(ACL_ROLE *grantee) static bool has_auth(LEX_USER *user, LEX *lex) { - return user->pwtext.length || user->plugin.length || user->auth.length || + return user->has_auth() || lex->ssl_type != SSL_TYPE_NOT_SPECIFIED || lex->ssl_cipher || - lex->x509_issuer || lex->x509_subject || - lex->mqh.specified_limits; -} - -static bool fix_and_copy_user(LEX_USER *to, LEX_USER *from, THD *thd) -{ - if (to != from) - { - /* preserve authentication information, if LEX_USER was reallocated */ - to->pwtext= from->pwtext; - to->plugin= from->plugin; - to->auth= from->auth; - } - return false; + lex->x509_issuer || lex->x509_subject || lex->mqh.specified_limits; } static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, THD *thd) { - if (fix_and_copy_user(to, from, thd)) - return true; + to->auth= from->auth; // if changing auth for an existing user if (has_auth(to, thd->lex) && find_user_exact(to->host.str, to->user.str)) @@ -8364,25 +8536,31 @@ static void add_user_parameters(String *result, ACL_USER* acl_user, system_charset_info); result->append('\''); - if (acl_user->plugin.str == native_password_plugin_name.str || - acl_user->plugin.str == old_password_plugin_name.str) + if (acl_user->nauth == 1 && + (acl_user->auth->plugin.str == native_password_plugin_name.str || + acl_user->auth->plugin.str == old_password_plugin_name.str)) { - if (acl_user->auth_string.length) + if (acl_user->auth->auth_string.length) { result->append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); - result->append(&acl_user->auth_string); + result->append(&acl_user->auth->auth_string); result->append('\''); } } else { result->append(STRING_WITH_LEN(" IDENTIFIED VIA ")); - result->append(&acl_user->plugin); - if (acl_user->auth_string.length) + for (uint i=0; i < acl_user->nauth; i++) { - result->append(STRING_WITH_LEN(" USING '")); - result->append(&acl_user->auth_string); - result->append('\''); + if (i) + result->append(STRING_WITH_LEN(" OR ")); + result->append(&acl_user->auth[i].plugin); + if (acl_user->auth[i].auth_string.length) + { + result->append(STRING_WITH_LEN(" USING '")); + result->append(&acl_user->auth[i].auth_string); + result->append('\''); + } } } /* "show grants" SSL related stuff */ @@ -11023,20 +11201,14 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, thd->make_lex_string(&combo->user, combo->user.str, strlen(combo->user.str)); thd->make_lex_string(&combo->host, combo->host.str, strlen(combo->host.str)); - combo->reset_auth(); - - if(au) - { - combo->plugin= au->plugin; - combo->auth= au->auth_string; - } + combo->auth= NULL; if (user_list.push_back(combo, thd->mem_root)) DBUG_RETURN(TRUE); thd->lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; thd->lex->ssl_cipher= thd->lex->x509_subject= thd->lex->x509_issuer= 0; - bzero((char*) &thd->lex->mqh, sizeof(thd->lex->mqh)); + bzero(&thd->lex->mqh, sizeof(thd->lex->mqh)); /* Only care about whether the operation failed or succeeded @@ -11294,7 +11466,7 @@ static int show_database_grants(THD *thd, SHOW_VAR *var, char *buff, } #else -static bool set_user_salt_if_needed(ACL_USER *, plugin_ref) +static bool set_user_salt_if_needed(ACL_USER *, int, plugin_ref) { return 0; } bool check_grant(THD *, ulong, TABLE_LIST *, bool, uint, bool) { return 0; } @@ -12078,6 +12250,7 @@ struct MPVIO_EXT :public MYSQL_PLUGIN_VIO char *pkt; uint pkt_len; } cached_server_packet; + uint curr_auth; ///< an index in acl_user->auth[] int packets_read, packets_written; ///< counters for send/received packets bool make_it_fail; /** when plugin returns a failure this tells us what really happened */ @@ -12141,7 +12314,7 @@ static void login_failed_error(THD *thd) static bool send_server_handshake_packet(MPVIO_EXT *mpvio, const char *data, uint data_len) { - DBUG_ASSERT(mpvio->status == MPVIO_EXT::FAILURE); + DBUG_ASSERT(mpvio->status == MPVIO_EXT::RESTART); DBUG_ASSERT(data_len <= 255); THD *thd= mpvio->auth_info.thd; @@ -12295,14 +12468,10 @@ static bool secure_auth(THD *thd) static bool send_plugin_request_packet(MPVIO_EXT *mpvio, const uchar *data, uint data_len) { - DBUG_ASSERT(mpvio->packets_written == 1); - DBUG_ASSERT(mpvio->packets_read == 1); NET *net= &mpvio->auth_info.thd->net; static uchar switch_plugin_request_buf[]= { 254 }; DBUG_ENTER("send_plugin_request_packet"); - mpvio->status= MPVIO_EXT::FAILURE; // the status is no longer RESTART - const char *client_auth_plugin= ((st_mysql_auth *) (plugin_decl(mpvio->plugin)->info))->client_auth_plugin; @@ -12437,26 +12606,19 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio) } /* user account requires non-default plugin and the client is too old */ - if (mpvio->acl_user->plugin.str != native_password_plugin_name.str && - mpvio->acl_user->plugin.str != old_password_plugin_name.str && + if (mpvio->acl_user->auth->plugin.str != native_password_plugin_name.str && + mpvio->acl_user->auth->plugin.str != old_password_plugin_name.str && !(mpvio->auth_info.thd->client_capabilities & CLIENT_PLUGIN_AUTH)) { - DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str, - native_password_plugin_name.str)); - DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str, - old_password_plugin_name.str)); + DBUG_ASSERT(my_strcasecmp(system_charset_info, + mpvio->acl_user->auth->plugin.str, native_password_plugin_name.str)); + DBUG_ASSERT(my_strcasecmp(system_charset_info, + mpvio->acl_user->auth->plugin.str, old_password_plugin_name.str)); my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0)); general_log_print(mpvio->auth_info.thd, COM_CONNECT, ER_THD(mpvio->auth_info.thd, ER_NOT_SUPPORTED_AUTH_MODE)); DBUG_RETURN (1); } - - DBUG_PRINT("info", ("exit: user=%s, auth_string=%s, authenticated as=%s" - "plugin=%s", - mpvio->auth_info.user_name, - mpvio->auth_info.auth_string, - mpvio->auth_info.authenticated_as, - mpvio->acl_user->plugin.str)); DBUG_RETURN(0); } @@ -12609,15 +12771,13 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) client_plugin= native_password_plugin_name.str; else { - client_plugin= old_password_plugin_name.str; /* - For a passwordless accounts we use native_password_plugin. - But when an old 4.0 client connects to it, we change it to - old_password_plugin, otherwise MySQL will think that server - and client plugins don't match. + Normally old clients use old_password_plugin, but for + a passwordless accounts we use native_password_plugin. + See guess_auth_plugin(). */ - if (mpvio->acl_user->auth_string.length == 0) - mpvio->acl_user->plugin= old_password_plugin_name; + client_plugin= passwd_len ? old_password_plugin_name.str + : native_password_plugin_name.str; } } @@ -12860,15 +13020,13 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, client_plugin= native_password_plugin_name.str; else { - client_plugin= old_password_plugin_name.str; /* - For a passwordless accounts we use native_password_plugin. - But when an old 4.0 client connects to it, we change it to - old_password_plugin, otherwise MySQL will think that server - and client plugins don't match. + Normally old clients use old_password_plugin, but for + a passwordless accounts we use native_password_plugin. + See guess_auth_plugin(). */ - if (mpvio->acl_user->auth_string.length == 0) - mpvio->acl_user->plugin= old_password_plugin_name; + client_plugin= passwd_len ? old_password_plugin_name.str + : native_password_plugin_name.str; } } @@ -12886,7 +13044,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, restarted and a server auth plugin will read the data that the client has just send. Cache them to return in the next server_mpvio_read_packet(). */ - if (!lex_string_eq(&mpvio->acl_user->plugin, plugin_name(mpvio->plugin))) + if (!lex_string_eq(&mpvio->acl_user->auth->plugin, plugin_name(mpvio->plugin))) { mpvio->cached_client_reply.pkt= passwd; mpvio->cached_client_reply.pkt_len= (uint)passwd_len; @@ -12966,6 +13124,7 @@ static int server_mpvio_write_packet(MYSQL_PLUGIN_VIO *param, res= my_net_write(&mpvio->auth_info.thd->net, packet, packet_len) || net_flush(&mpvio->auth_info.thd->net); } + mpvio->status= MPVIO_EXT::FAILURE; // the status is no longer RESTART mpvio->packets_written++; DBUG_RETURN(res); } @@ -12983,10 +13142,41 @@ static int server_mpvio_write_packet(MYSQL_PLUGIN_VIO *param, static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) { MPVIO_EXT * const mpvio= (MPVIO_EXT *) param; + MYSQL_SERVER_AUTH_INFO * const ai= &mpvio->auth_info; ulong pkt_len; DBUG_ENTER("server_mpvio_read_packet"); - if (mpvio->packets_written == 0) + if (mpvio->status == MPVIO_EXT::RESTART) { + const char *client_auth_plugin= + ((st_mysql_auth *) (plugin_decl(mpvio->plugin)->info))->client_auth_plugin; + if (client_auth_plugin == 0) + { + mpvio->status= MPVIO_EXT::FAILURE; + pkt_len= 0; + *buf= 0; + goto done; + } + + if (mpvio->cached_client_reply.pkt) + { + DBUG_ASSERT(mpvio->packets_read > 0); + /* + if the have the data cached from the last server_mpvio_read_packet + (which can be the case if it's a restarted authentication) + and a client has used the correct plugin, then we can return the + cached data straight away and avoid one round trip. + */ + if (my_strcasecmp(system_charset_info, mpvio->cached_client_reply.plugin, + client_auth_plugin) == 0) + { + mpvio->status= MPVIO_EXT::FAILURE; + pkt_len= mpvio->cached_client_reply.pkt_len; + *buf= (uchar*) mpvio->cached_client_reply.pkt; + mpvio->packets_read++; + goto done; + } + } + /* plugin wants to read the data without sending anything first. send an empty packet to force a server handshake packet to be sent @@ -12994,44 +13184,10 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) if (server_mpvio_write_packet(mpvio, 0, 0)) pkt_len= packet_error; else - pkt_len= my_net_read(&mpvio->auth_info.thd->net); - } - else if (mpvio->cached_client_reply.pkt) - { - DBUG_ASSERT(mpvio->status == MPVIO_EXT::RESTART); - DBUG_ASSERT(mpvio->packets_read > 0); - /* - if the have the data cached from the last server_mpvio_read_packet - (which can be the case if it's a restarted authentication) - and a client has used the correct plugin, then we can return the - cached data straight away and avoid one round trip. - */ - const char *client_auth_plugin= - ((st_mysql_auth *) (plugin_decl(mpvio->plugin)->info))->client_auth_plugin; - if (client_auth_plugin == 0 || - my_strcasecmp(system_charset_info, mpvio->cached_client_reply.plugin, - client_auth_plugin) == 0) - { - mpvio->status= MPVIO_EXT::FAILURE; - pkt_len= mpvio->cached_client_reply.pkt_len; - *buf= (uchar*) mpvio->cached_client_reply.pkt; - mpvio->cached_client_reply.pkt= 0; - mpvio->packets_read++; - goto done; - } - - /* - But if the client has used the wrong plugin, the cached data are - useless. Furthermore, we have to send a "change plugin" request - to the client. - */ - if (server_mpvio_write_packet(mpvio, 0, 0)) - pkt_len= packet_error; - else - pkt_len= my_net_read(&mpvio->auth_info.thd->net); + pkt_len= my_net_read(&ai->thd->net); } else - pkt_len= my_net_read(&mpvio->auth_info.thd->net); + pkt_len= my_net_read(&ai->thd->net); if (unlikely(pkt_len == packet_error)) goto err; @@ -13049,24 +13205,24 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) goto err; } else - *buf= mpvio->auth_info.thd->net.read_pos; + *buf= ai->thd->net.read_pos; done: - if (set_user_salt_if_needed(mpvio->acl_user, mpvio->plugin)) + if (set_user_salt_if_needed(mpvio->acl_user, mpvio->curr_auth, mpvio->plugin)) goto err; - mpvio->auth_info.user_name= mpvio->auth_info.thd->security_ctx->user; - mpvio->auth_info.user_name_length= (uint)strlen(mpvio->auth_info.user_name); - mpvio->auth_info.auth_string= mpvio->acl_user->salt.str; - mpvio->auth_info.auth_string_length= (ulong) mpvio->acl_user->salt.length; - strmake_buf(mpvio->auth_info.authenticated_as, mpvio->acl_user->user.str); + ai->user_name= ai->thd->security_ctx->user; + ai->user_name_length= (uint) strlen(ai->user_name); + ai->auth_string= mpvio->acl_user->auth[mpvio->curr_auth].salt.str; + ai->auth_string_length= (ulong) mpvio->acl_user->auth[mpvio->curr_auth].salt.length; + strmake_buf(ai->authenticated_as, mpvio->acl_user->user.str); DBUG_RETURN((int)pkt_len); err: if (mpvio->status == MPVIO_EXT::FAILURE) { - if (!mpvio->auth_info.thd->is_error()) + if (!ai->thd->is_error()) my_error(ER_HANDSHAKE_ERROR, MYF(0)); } DBUG_RETURN(-1); @@ -13196,26 +13352,25 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user) static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name, MPVIO_EXT *mpvio) { - int res= CR_OK, old_status= MPVIO_EXT::FAILURE; + int res= CR_OK; bool unlock_plugin= false; plugin_ref plugin= get_auth_plugin(thd, *auth_plugin_name, &unlock_plugin); mpvio->plugin= plugin; mpvio->auth_info.user_name= NULL; - old_status= mpvio->status; if (plugin) { - st_mysql_auth *auth= (st_mysql_auth *) plugin_decl(plugin)->info; - switch (auth->interface_version >> 8) { + st_mysql_auth *info= (st_mysql_auth *) plugin_decl(plugin)->info; + switch (info->interface_version >> 8) { case 0x02: - res= auth->authenticate_user(mpvio, &mpvio->auth_info); + res= info->authenticate_user(mpvio, &mpvio->auth_info); break; case 0x01: { MYSQL_SERVER_AUTH_INFO_0x0100 compat; compat.downgrade(&mpvio->auth_info); - res= auth->authenticate_user(mpvio, (MYSQL_SERVER_AUTH_INFO *)&compat); + res= info->authenticate_user(mpvio, (MYSQL_SERVER_AUTH_INFO *)&compat); compat.upgrade(&mpvio->auth_info); } break; @@ -13235,17 +13390,6 @@ static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name, res= CR_ERROR; } - /* - If the status was MPVIO_EXT::RESTART before the authenticate_user() call - it can never be MPVIO_EXT::RESTART after the call, because any call - to write_packet() or read_packet() will reset the status. - - But (!) if a plugin never called a read_packet() or write_packet(), the - status will stay unchanged. We'll fix it, by resetting the status here. - */ - if (old_status == MPVIO_EXT::RESTART && mpvio->status == MPVIO_EXT::RESTART) - mpvio->status= MPVIO_EXT::FAILURE; // reset to the default - return res; } @@ -13298,7 +13442,6 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) { int res= CR_OK; MPVIO_EXT mpvio; - const LEX_CSTRING *auth_plugin_name= default_auth_plugin_name; enum enum_server_command command= com_change_user_pkt_len ? COM_CHANGE_USER : COM_CONNECT; DBUG_ENTER("acl_authenticate"); @@ -13306,9 +13449,9 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) bzero(&mpvio, sizeof(mpvio)); mpvio.read_packet= server_mpvio_read_packet; mpvio.write_packet= server_mpvio_write_packet; + mpvio.cached_client_reply.plugin= ""; mpvio.info= server_mpvio_info; - mpvio.status= MPVIO_EXT::FAILURE; - mpvio.make_it_fail= false; + mpvio.status= MPVIO_EXT::RESTART; mpvio.auth_info.thd= thd; mpvio.auth_info.host_or_ip= thd->security_ctx->host_or_ip; mpvio.auth_info.host_or_ip_length= @@ -13324,6 +13467,8 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) if (parse_com_change_user_packet(&mpvio, com_change_user_pkt_len)) DBUG_RETURN(1); + res= mpvio.status == MPVIO_EXT::SUCCESS ? CR_OK : CR_ERROR; + DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART || mpvio.status == MPVIO_EXT::SUCCESS); } @@ -13339,29 +13484,33 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) the correct plugin. */ - res= do_auth_once(thd, auth_plugin_name, &mpvio); + res= do_auth_once(thd, default_auth_plugin_name, &mpvio); } - /* - retry the authentication, if - after receiving the user name - - we found that we need to switch to a non-default plugin - */ - if (mpvio.status == MPVIO_EXT::RESTART) + Security_context * const sctx= thd->security_ctx; + const ACL_USER * acl_user= mpvio.acl_user; + + if (acl_user) { - DBUG_ASSERT(mpvio.acl_user); - DBUG_ASSERT(command == COM_CHANGE_USER || - !lex_string_eq(auth_plugin_name, &mpvio.acl_user->plugin)); - auth_plugin_name= &mpvio.acl_user->plugin; - res= do_auth_once(thd, auth_plugin_name, &mpvio); + /* + retry the authentication with curr_auth==0 if after receiving the user + name we found that we need to switch to a non-default plugin + */ + for (mpvio.curr_auth= mpvio.status != MPVIO_EXT::RESTART; + res != CR_OK && mpvio.curr_auth < acl_user->nauth; + mpvio.curr_auth++) + { + thd->clear_error(); + mpvio.status= MPVIO_EXT::RESTART; + res= do_auth_once(thd, &acl_user->auth[mpvio.curr_auth].plugin, &mpvio); + } } + if (mpvio.make_it_fail && res == CR_OK) { mpvio.status= MPVIO_EXT::FAILURE; res= CR_ERROR; } - - Security_context *sctx= thd->security_ctx; - const ACL_USER *acl_user= mpvio.acl_user; thd->password= mpvio.auth_info.password_used; // remember for error messages @@ -13389,7 +13538,6 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) if (res > CR_OK && mpvio.status != MPVIO_EXT::SUCCESS) { Host_errors errors; - DBUG_ASSERT(mpvio.status == MPVIO_EXT::FAILURE); switch (res) { case CR_AUTH_PLUGIN_ERROR: @@ -13628,12 +13776,11 @@ static int native_password_authenticate(MYSQL_PLUGIN_VIO *vio, /* generate the scramble, or reuse the old one */ if (thd->scramble[SCRAMBLE_LENGTH]) - { thd_create_random_password(thd, thd->scramble, SCRAMBLE_LENGTH); - /* and send it to the client */ - if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1)) - DBUG_RETURN(CR_AUTH_HANDSHAKE); - } + + /* and send it to the client */ + if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1)) + DBUG_RETURN(CR_AUTH_HANDSHAKE); /* reply and authenticate */ @@ -13748,12 +13895,10 @@ static int old_password_authenticate(MYSQL_PLUGIN_VIO *vio, /* generate the scramble, or reuse the old one */ if (thd->scramble[SCRAMBLE_LENGTH]) - { thd_create_random_password(thd, thd->scramble, SCRAMBLE_LENGTH); - /* and send it to the client */ - if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1)) - return CR_AUTH_HANDSHAKE; - } + /* and send it to the client */ + if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1)) + return CR_AUTH_HANDSHAKE; /* read the reply and authenticate */ if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 78bfbd4dbd2..22e849e6322 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2018, MariaDB Corporation. + Copyright (c) 2008, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -5577,7 +5577,7 @@ void THD::get_definer(LEX_USER *definer, bool role) { definer->user= invoker.user; definer->host= invoker.host; - definer->reset_auth(); + definer->auth= NULL; } else #endif diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7360ecb62da..c39d7de096e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2008, 2018, MariaDB + Copyright (c) 2008, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -9829,8 +9829,7 @@ void get_default_definer(THD *thd, LEX_USER *definer, bool role) definer->host.length= strlen(definer->host.str); } definer->user.length= strlen(definer->user.str); - - definer->reset_auth(); + definer->auth= NULL; } @@ -9889,7 +9888,7 @@ LEX_USER *create_definer(THD *thd, LEX_CSTRING *user_name, definer->user= *user_name; definer->host= *host_name; - definer->reset_auth(); + definer->auth= NULL; return definer; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f689180977c..81ece13e1c5 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2016, MariaDB + Copyright (c) 2010, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -722,6 +722,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) class sp_lex_cursor *sp_cursor_stmt; LEX_CSTRING *lex_str_ptr; LEX_USER *lex_user; + USER_AUTH *user_auth; List *cond_info_list; List *dyncol_def_list; List *item_list; @@ -1945,6 +1946,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type user grant_user grant_role user_or_role current_role admin_option_for_role user_maybe_role +%type opt_auth_str auth_expression auth_token + %type opt_collate charset_name @@ -15520,11 +15523,9 @@ ident_or_text: user_maybe_role: ident_or_text { - if (unlikely(!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))) + if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user = $1; - $$->host= null_clex_str; // User or Role, see get_current_user() - $$->reset_auth(); if (unlikely(check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -15533,10 +15534,9 @@ user_maybe_role: } | ident_or_text '@' ident_or_text { - if (unlikely(!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))) + if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user = $1; $$->host=$3; - $$->reset_auth(); if (unlikely(check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -15566,8 +15566,7 @@ user_maybe_role: if (unlikely(!($$=(LEX_USER*)thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user= current_user; - $$->plugin= empty_clex_str; - $$->auth= empty_clex_str; + $$->auth= new (thd->mem_root) USER_AUTH(); } ; @@ -16550,21 +16549,29 @@ opt_for_user: thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; lex->definer->user= current_user; - lex->definer->plugin= empty_clex_str; - lex->definer->auth= empty_clex_str; + lex->definer->auth= new (thd->mem_root) USER_AUTH(); } | FOR_SYM user equal { Lex->definer= $2; } ; text_or_password: - TEXT_STRING { Lex->definer->auth= $1;} - | PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->pwtext= $3; } + TEXT_STRING + { + Lex->definer->auth= new (thd->mem_root) USER_AUTH(); + Lex->definer->auth->auth_str= $1; + } + | PASSWORD_SYM '(' TEXT_STRING ')' + { + Lex->definer->auth= new (thd->mem_root) USER_AUTH(); + Lex->definer->auth->pwtext= $3; + } | OLD_PASSWORD_SYM '(' TEXT_STRING ')' { - Lex->definer->pwtext= $3; - Lex->definer->auth.str= Item_func_password::alloc(thd, + Lex->definer->auth= new (thd->mem_root) USER_AUTH(); + Lex->definer->auth->pwtext= $3; + Lex->definer->auth->auth_str.str= Item_func_password::alloc(thd, $3.str, $3.length, Item_func_password::OLD); - Lex->definer->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; + Lex->definer->auth->auth_str.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; } ; @@ -16938,7 +16945,7 @@ current_role: if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user= current_role; - $$->reset_auth(); + $$->auth= NULL; } ; @@ -16955,7 +16962,7 @@ grant_role: MYSQL_YYABORT; $$->user= $1; $$->host= empty_clex_str; - $$->reset_auth(); + $$->auth= NULL; if (unlikely(check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -17152,37 +17159,65 @@ grant_user: user IDENTIFIED_SYM BY TEXT_STRING { $$= $1; - $1->pwtext= $4; + $1->auth= new (thd->mem_root) USER_AUTH(); + $1->auth->pwtext= $4; } | user IDENTIFIED_SYM BY PASSWORD_SYM TEXT_STRING { $$= $1; - $1->auth= $5; + $1->auth= new (thd->mem_root) USER_AUTH(); + $1->auth->auth_str= $5; } - | user IDENTIFIED_SYM via_or_with ident_or_text + | user IDENTIFIED_SYM via_or_with auth_expression { $$= $1; - $1->plugin= $4; - $1->auth= empty_clex_str; - } - | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as - TEXT_STRING_sys - { - $$= $1; - $1->plugin= $4; - $1->auth= $6; - } - | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as - PASSWORD_SYM '(' TEXT_STRING ')' - { - $$= $1; - $1->plugin= $4; - $1->pwtext= $8; + $1->auth= $4; } | user_or_role { $$= $1; } ; +auth_expression: + auth_token OR_SYM auth_expression + { + $$= $1; + DBUG_ASSERT($$->next == NULL); + $$->next= $3; + } + | auth_token + { + $$= $1; + } + ; + +auth_token: + ident_or_text opt_auth_str + { + $$= $2; + $$->plugin= $1; + } + ; + +opt_auth_str: + /* empty */ + { + if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH)))) + MYSQL_YYABORT; + } + | using_or_as TEXT_STRING_sys + { + if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH)))) + MYSQL_YYABORT; + $$->auth_str= $2; + } + | using_or_as PASSWORD_SYM '(' TEXT_STRING ')' + { + if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH)))) + MYSQL_YYABORT; + $$->pwtext= $4; + } + ; + opt_column_list: /* empty */ { diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 0fa45dacd5e..aa622b61771 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2016, MariaDB + Copyright (c) 2010, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -218,6 +218,7 @@ void ORAerror(THD *thd, const char *s) class sp_lex_cursor *sp_cursor_stmt; LEX_CSTRING *lex_str_ptr; LEX_USER *lex_user; + USER_AUTH *user_auth; List *cond_info_list; List *dyncol_def_list; List *item_list; @@ -1449,6 +1450,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type user grant_user grant_role user_or_role current_role admin_option_for_role user_maybe_role +%type opt_auth_str auth_expression auth_token + %type opt_collate charset_name @@ -15595,11 +15598,9 @@ ident_or_text: user_maybe_role: ident_or_text { - if (unlikely(!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))) + if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user = $1; - $$->host= null_clex_str; // User or Role, see get_current_user() - $$->reset_auth(); if (unlikely(check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -15608,10 +15609,9 @@ user_maybe_role: } | ident_or_text '@' ident_or_text { - if (unlikely(!($$=(LEX_USER*) thd->alloc(sizeof(LEX_USER))))) + if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user = $1; $$->host=$3; - $$->reset_auth(); if (unlikely(check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -15641,8 +15641,7 @@ user_maybe_role: if (unlikely(!($$=(LEX_USER*)thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user= current_user; - $$->plugin= empty_clex_str; - $$->auth= empty_clex_str; + $$->auth= new (thd->mem_root) USER_AUTH(); } ; @@ -16687,21 +16686,29 @@ opt_for_user: thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; lex->definer->user= current_user; - lex->definer->plugin= empty_clex_str; - lex->definer->auth= empty_clex_str; + lex->definer->auth= new (thd->mem_root) USER_AUTH(); } | FOR_SYM user equal { Lex->definer= $2; } ; text_or_password: - TEXT_STRING { Lex->definer->auth= $1;} - | PASSWORD_SYM '(' TEXT_STRING ')' { Lex->definer->pwtext= $3; } + TEXT_STRING + { + Lex->definer->auth= new (thd->mem_root) USER_AUTH(); + Lex->definer->auth->auth_str= $1; + } + | PASSWORD_SYM '(' TEXT_STRING ')' + { + Lex->definer->auth= new (thd->mem_root) USER_AUTH(); + Lex->definer->auth->pwtext= $3; + } | OLD_PASSWORD_SYM '(' TEXT_STRING ')' { - Lex->definer->pwtext= $3; - Lex->definer->auth.str= Item_func_password::alloc(thd, + Lex->definer->auth= new (thd->mem_root) USER_AUTH(); + Lex->definer->auth->pwtext= $3; + Lex->definer->auth->auth_str.str= Item_func_password::alloc(thd, $3.str, $3.length, Item_func_password::OLD); - Lex->definer->auth.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; + Lex->definer->auth->auth_str.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; } ; @@ -17075,7 +17082,7 @@ current_role: if (unlikely(!($$=(LEX_USER*) thd->calloc(sizeof(LEX_USER))))) MYSQL_YYABORT; $$->user= current_role; - $$->reset_auth(); + $$->auth= NULL; } ; @@ -17092,7 +17099,7 @@ grant_role: MYSQL_YYABORT; $$->user= $1; $$->host= empty_clex_str; - $$->reset_auth(); + $$->auth= NULL; if (unlikely(check_string_char_length(&$$->user, ER_USERNAME, username_char_length, @@ -17289,37 +17296,65 @@ grant_user: user IDENTIFIED_SYM BY TEXT_STRING { $$= $1; - $1->pwtext= $4; + $1->auth= new (thd->mem_root) USER_AUTH(); + $1->auth->pwtext= $4; } | user IDENTIFIED_SYM BY PASSWORD_SYM TEXT_STRING { $$= $1; - $1->auth= $5; + $1->auth= new (thd->mem_root) USER_AUTH(); + $1->auth->auth_str= $5; } - | user IDENTIFIED_SYM via_or_with ident_or_text + | user IDENTIFIED_SYM via_or_with auth_expression { $$= $1; - $1->plugin= $4; - $1->auth= empty_clex_str; - } - | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as - TEXT_STRING_sys - { - $$= $1; - $1->plugin= $4; - $1->auth= $6; - } - | user IDENTIFIED_SYM via_or_with ident_or_text using_or_as - PASSWORD_SYM '(' TEXT_STRING ')' - { - $$= $1; - $1->plugin= $4; - $1->pwtext= $8; + $1->auth= $4; } | user_or_role { $$= $1; } ; +auth_expression: + auth_token OR_SYM auth_expression + { + $$= $1; + DBUG_ASSERT($$->next == NULL); + $$->next= $3; + } + | auth_token + { + $$= $1; + } + ; + +auth_token: + ident_or_text opt_auth_str + { + $$= $2; + $$->plugin= $1; + } + ; + +opt_auth_str: + /* empty */ + { + if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH)))) + MYSQL_YYABORT; + } + | using_or_as TEXT_STRING_sys + { + if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH)))) + MYSQL_YYABORT; + $$->auth_str= $2; + } + | using_or_as PASSWORD_SYM '(' TEXT_STRING ')' + { + if (!($$=(USER_AUTH*) thd->calloc(sizeof(USER_AUTH)))) + MYSQL_YYABORT; + $$->pwtext= $4; + } + ; + opt_column_list: /* empty */ { diff --git a/sql/structs.h b/sql/structs.h index 3e29e137376..4c4cf137bc5 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -1,8 +1,8 @@ #ifndef STRUCTS_INCLUDED #define STRUCTS_INCLUDED -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. - Copyright (c) 2017, MariaDB Corporation. +/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. + Copyright (c) 2009, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -203,6 +203,17 @@ extern const char *show_comp_option_name[]; typedef int *(*update_var)(THD *, struct st_mysql_show_var *); +struct USER_AUTH : public Sql_alloc +{ + LEX_CSTRING plugin, auth_str, pwtext; + USER_AUTH *next; + USER_AUTH() : next(NULL) + { + plugin.str= auth_str.str= ""; + pwtext.str= NULL; + plugin.length= auth_str.length= pwtext.length= 0; + } +}; struct AUTHID { @@ -227,12 +238,10 @@ struct AUTHID struct LEX_USER: public AUTHID { - LEX_CSTRING plugin, auth, pwtext; - void reset_auth() + USER_AUTH *auth; + bool has_auth() { - pwtext.length= plugin.length= auth.length= 0; - pwtext.str= 0; - plugin.str= auth.str= ""; + return auth && (auth->plugin.length || auth->auth_str.length || auth->pwtext.length); } }; From 7075d7fce626ee915c9ae9308cfb4a8120e83e44 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 29 Jan 2019 12:55:33 +0100 Subject: [PATCH 36/91] MDEV-11340 Allow multiple alternative authentication methods for the same user test a multi-auth with a missing auth plugin on the client update (and simplify) plugin_auth.test to match --- libmariadb | 2 +- mysql-test/main/plugin_auth.result | 33 ++++++------------ mysql-test/main/plugin_auth.test | 38 ++++----------------- mysql-test/suite/plugins/r/multiauth.result | 24 +++++++++++++ mysql-test/suite/plugins/t/multiauth.test | 20 ++++++++++- 5 files changed, 61 insertions(+), 56 deletions(-) diff --git a/libmariadb b/libmariadb index 1e4b08bd298..beb9d5ea899 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 1e4b08bd2989c664f6f43e0dbb2c71be9552bc8c +Subproject commit beb9d5ea8994bb90361c4b9f3d926eee24055178 diff --git a/mysql-test/main/plugin_auth.result b/mysql-test/main/plugin_auth.result index 7c3d029ad7d..d69246f8c7d 100644 --- a/mysql-test/main/plugin_auth.result +++ b/mysql-test/main/plugin_auth.result @@ -11,6 +11,8 @@ SELECT plugin,authentication_string FROM mysql.user WHERE User='plug'; plugin authentication_string test_plugin_server plug_dest ## test plugin auth +connect(localhost,plug,plug_dest,test,MYSQL_PORT,MYSQL_SOCK); +connect plug_con,localhost,plug,plug_dest; ERROR 28000: Access denied for user 'plug'@'localhost' (using password: YES) GRANT PROXY ON plug_dest TO plug; test proxies_priv columns @@ -32,7 +34,6 @@ proxies_priv CREATE TABLE `proxies_priv` ( KEY `Grantor` (`Grantor`) ) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='User proxy privileges' connect plug_con,localhost,plug,plug_dest; -connection plug_con; select USER(),CURRENT_USER(); USER() CURRENT_USER() plug@localhost plug_dest@% @@ -41,11 +42,18 @@ SET PASSWORD = PASSWORD('plug_dest'); connection default; disconnect plug_con; ## test bad credentials +connect(localhost,plug,bad_credentials,test,MYSQL_PORT,MYSQL_SOCK); +connect plug_con,localhost,plug,bad_credentials; ERROR 28000: Access denied for user 'plug'@'localhost' (using password: YES) -## test bad default plugin : should get CR_AUTH_PLUGIN_CANNOT_LOAD +## test bad default plugin : nothing bad happens, as that plugin was't required by the server +connect plug_con_wrongp,localhost,plug,plug_dest,,,,,wrong_plugin_name; +select USER(),CURRENT_USER(); +USER() CURRENT_USER() +plug@localhost plug_dest@% +connection default; +disconnect plug_con_wrongp; ## test correct default plugin connect plug_con_rightp,localhost,plug,plug_dest,,,,,auth_test_plugin; -connection plug_con_rightp; select USER(),CURRENT_USER(); USER() CURRENT_USER() plug@localhost plug_dest@% @@ -60,7 +68,6 @@ DROP USER grant_user; CREATE USER `Ÿ` IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; GRANT PROXY ON plug_dest TO `Ÿ`; connect non_ascii,localhost,Ÿ,plug_dest; -connection non_ascii; select USER(),CURRENT_USER(); USER() CURRENT_USER() Ÿ@localhost plug_dest@% @@ -74,7 +81,6 @@ GRANT ALL PRIVILEGES ON test_grant_db.* TO new_grant_user IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; GRANT PROXY ON plug_dest TO new_grant_user; connect plug_con_grant,localhost,new_grant_user,plug_dest; -connection plug_con_grant; select USER(),CURRENT_USER(); USER() CURRENT_USER() new_grant_user@localhost plug_dest@% @@ -91,7 +97,6 @@ connect(localhost,new_grant_user,plug_dest,test,MYSQL_PORT,MYSQL_SOCK); connect plug_con_grant_deny,localhost,new_grant_user,plug_dest; ERROR 28000: Access denied for user 'new_grant_user'@'localhost' (using password: YES) connect plug_con_grant,localhost,new_grant_user,new_password; -connection plug_con_grant; select USER(),CURRENT_USER(); USER() CURRENT_USER() new_grant_user@localhost new_grant_user@% @@ -133,8 +138,6 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp REVOKE PROXY ON grant_plug_dest FROM grant_plug; ERROR 42000: There is no such grant defined for user 'grant_plug' on host '%' connect grant_plug_dest_con,localhost,grant_plug_dest,grant_plug_dest_passwd; -connection grant_plug_dest_con; -in grant_plug_dest_con ## testing what an ordinary user can grant this should fail : no rights to grant all GRANT PROXY ON ''@'%%' TO grant_plug; @@ -158,7 +161,6 @@ this should fail : can't create users GRANT PROXY ON grant_plug_dest TO grant_plug@localhost; ERROR 42000: You are not allowed to create a user with GRANT connection default; -in default connection disconnect grant_plug_dest_con; # test what root can grant should work : root has PROXY to all users @@ -170,12 +172,9 @@ WITH GRANT OPTION; need USAGE : PROXY doesn't contain it. GRANT USAGE on *.* TO proxy_admin; connect proxy_admin_con,localhost,proxy_admin,test; -connection proxy_admin_con; -in proxy_admin_con; should work : proxy_admin has proxy to ''@'%%' GRANT PROXY ON future_user TO grant_plug; connection default; -in default connection disconnect proxy_admin_con; SHOW GRANTS FOR grant_plug; Grants for grant_plug@% @@ -221,13 +220,10 @@ SELECT @@LOCAL.proxy_user; @@LOCAL.proxy_user NULL connect plug_con,localhost,plug,plug_dest; -connection plug_con; -# in connection plug_con SELECT @@LOCAL.proxy_user; @@LOCAL.proxy_user 'plug'@'%' connection default; -# in connection default disconnect plug_con; ## cleanup DROP USER plug; @@ -253,13 +249,10 @@ SELECT @@LOCAL.external_user; @@LOCAL.external_user NULL connect plug_con,localhost,plug,plug_dest; -connection plug_con; -# in connection plug_con SELECT @@LOCAL.external_user; @@LOCAL.external_user plug_dest connection default; -# in connection default disconnect plug_con; ## cleanup DROP USER plug; @@ -315,7 +308,6 @@ REVOKE PROXY ON u2@localhost FROM u1@localhost; ERROR 28000: Access denied for user 'root'@'localhost' # go try graning proxy on itself, so that it will need the table connect proxy_granter_con,localhost,u2,; -connection proxy_granter_con; GRANT PROXY ON u2@localhost TO u1@localhost; ERROR 42S02: Table 'mysql.proxies_priv' doesn't exist REVOKE PROXY ON u2@localhost FROM u1@localhost; @@ -355,7 +347,6 @@ CREATE USER uplain@localhost IDENTIFIED WITH 'cleartext_plugin_server' ## test plugin auth ERROR 28000: Access denied for user 'uplain'@'localhost' (using password: YES) connect cleartext_con,localhost,uplain,cleartext_test; -connection cleartext_con; select USER(),CURRENT_USER(); USER() CURRENT_USER() uplain@localhost uplain@localhost @@ -474,7 +465,6 @@ CREATE USER bug12818542_dest@localhost IDENTIFIED BY 'bug12818542_dest_passwd'; GRANT PROXY ON bug12818542_dest@localhost TO bug12818542@localhost; connect bug12818542_con,localhost,bug12818542,bug12818542_dest; -connection bug12818542_con; SELECT USER(),CURRENT_USER(); USER() CURRENT_USER() bug12818542@localhost bug12818542_dest@localhost @@ -482,7 +472,6 @@ SET PASSWORD = PASSWORD('bruhaha'); connection default; disconnect bug12818542_con; connect bug12818542_con2,localhost,bug12818542,bug12818542_dest; -connection bug12818542_con2; SELECT USER(),CURRENT_USER(); USER() CURRENT_USER() bug12818542@localhost bug12818542_dest@localhost diff --git a/mysql-test/main/plugin_auth.test b/mysql-test/main/plugin_auth.test index 9af8f25d153..30e4fa6e0ad 100644 --- a/mysql-test/main/plugin_auth.test +++ b/mysql-test/main/plugin_auth.test @@ -15,10 +15,9 @@ CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd'; SELECT plugin,authentication_string FROM mysql.user WHERE User='plug'; --echo ## test plugin auth ---disable_query_log +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK --error ER_ACCESS_DENIED_ERROR : this should fail : no grant connect(plug_con,localhost,plug,plug_dest); ---enable_query_log GRANT PROXY ON plug_dest TO plug; --echo test proxies_priv columns @@ -28,8 +27,6 @@ SELECT * FROM mysql.proxies_priv WHERE user !='root'; SHOW CREATE TABLE mysql.proxies_priv; connect(plug_con,localhost,plug,plug_dest); - -connection plug_con; select USER(),CURRENT_USER(); --echo ## test SET PASSWORD @@ -40,22 +37,18 @@ connection default; disconnect plug_con; --echo ## test bad credentials ---disable_query_log +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK --error ER_ACCESS_DENIED_ERROR connect(plug_con,localhost,plug,bad_credentials); ---enable_query_log ---echo ## test bad default plugin : should get CR_AUTH_PLUGIN_CANNOT_LOAD ---disable_result_log ---disable_query_log ---error 2059 +--echo ## test bad default plugin : nothing bad happens, as that plugin was't required by the server connect(plug_con_wrongp,localhost,plug,plug_dest,,,,,wrong_plugin_name); ---enable_query_log ---enable_result_log +select USER(),CURRENT_USER(); +connection default; +disconnect plug_con_wrongp; --echo ## test correct default plugin connect(plug_con_rightp,localhost,plug,plug_dest,,,,,auth_test_plugin); -connection plug_con_rightp; select USER(),CURRENT_USER(); connection default; disconnect plug_con_rightp; @@ -72,7 +65,6 @@ CREATE USER `Ÿ` IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest'; GRANT PROXY ON plug_dest TO `Ÿ`; connect(non_ascii,localhost,Ÿ,plug_dest); -connection non_ascii; select USER(),CURRENT_USER(); connection default; @@ -90,7 +82,6 @@ GRANT ALL PRIVILEGES ON test_grant_db.* TO new_grant_user GRANT PROXY ON plug_dest TO new_grant_user; connect(plug_con_grant,localhost,new_grant_user,plug_dest); -connection plug_con_grant; select USER(),CURRENT_USER(); USE test_grant_db; CREATE TABLE t1 (a INT); @@ -108,7 +99,6 @@ GRANT ALL PRIVILEGES ON test_grant_db.* TO new_grant_user connect(plug_con_grant_deny,localhost,new_grant_user,plug_dest); connect(plug_con_grant,localhost,new_grant_user,new_password); -connection plug_con_grant; select USER(),CURRENT_USER(); USE test_grant_db; CREATE TABLE t1 (a INT); @@ -166,8 +156,6 @@ GRANT ALL SELECT,PROXY ON grant_plug_dest TO grant_plug; REVOKE PROXY ON grant_plug_dest FROM grant_plug; connect(grant_plug_dest_con,localhost,grant_plug_dest,grant_plug_dest_passwd); -connection grant_plug_dest_con; ---echo in grant_plug_dest_con --echo ## testing what an ordinary user can grant --echo this should fail : no rights to grant all @@ -209,7 +197,6 @@ REVOKE PROXY ON grant_plug_dest@localhost FROM grant_plug; GRANT PROXY ON grant_plug_dest TO grant_plug@localhost; connection default; ---echo in default connection disconnect grant_plug_dest_con; --echo # test what root can grant @@ -226,14 +213,11 @@ GRANT PROXY ON ''@'%%' TO proxy_admin IDENTIFIED BY 'test' GRANT USAGE on *.* TO proxy_admin; connect (proxy_admin_con,localhost,proxy_admin,test); -connection proxy_admin_con; ---echo in proxy_admin_con; --echo should work : proxy_admin has proxy to ''@'%%' GRANT PROXY ON future_user TO grant_plug; connection default; ---echo in default connection disconnect proxy_admin_con; SHOW GRANTS FOR grant_plug; @@ -275,11 +259,8 @@ SET LOCAL proxy_user = 'test'; SELECT @@LOCAL.proxy_user; connect(plug_con,localhost,plug,plug_dest); -connection plug_con; ---echo # in connection plug_con SELECT @@LOCAL.proxy_user; connection default; ---echo # in connection default disconnect plug_con; --echo ## cleanup @@ -304,11 +285,8 @@ SET LOCAL external_user = 'test'; SELECT @@LOCAL.external_user; connect(plug_con,localhost,plug,plug_dest); -connection plug_con; ---echo # in connection plug_con SELECT @@LOCAL.external_user; connection default; ---echo # in connection default disconnect plug_con; --echo ## cleanup @@ -382,7 +360,6 @@ REVOKE PROXY ON u2@localhost FROM u1@localhost; --echo # go try graning proxy on itself, so that it will need the table connect(proxy_granter_con,localhost,u2,); -connection proxy_granter_con; --error ER_NO_SUCH_TABLE GRANT PROXY ON u2@localhost TO u1@localhost; @@ -438,7 +415,6 @@ connect(cleartext_fail_con,localhost,uplain,cleartext_test2); --enable_query_log connect(cleartext_con,localhost,uplain,cleartext_test); -connection cleartext_con; select USER(),CURRENT_USER(); connection default; @@ -571,7 +547,6 @@ CREATE USER bug12818542_dest@localhost GRANT PROXY ON bug12818542_dest@localhost TO bug12818542@localhost; connect(bug12818542_con,localhost,bug12818542,bug12818542_dest); -connection bug12818542_con; SELECT USER(),CURRENT_USER(); SET PASSWORD = PASSWORD('bruhaha'); @@ -580,7 +555,6 @@ connection default; disconnect bug12818542_con; connect(bug12818542_con2,localhost,bug12818542,bug12818542_dest); -connection bug12818542_con2; SELECT USER(),CURRENT_USER(); connection default; diff --git a/mysql-test/suite/plugins/r/multiauth.result b/mysql-test/suite/plugins/r/multiauth.result index 998e6d4dce7..d10744daf89 100644 --- a/mysql-test/suite/plugins/r/multiauth.result +++ b/mysql-test/suite/plugins/r/multiauth.result @@ -14,6 +14,7 @@ select user(), current_user(), database(); user() current_user() database() mysqltest1@localhost mysqltest1@% test # name does not match, password bad = failure +mysqltest: Could not open connection 'default': 1045 Access denied for user 'mysqltest1'@'localhost' (using password: YES) drop user USER, mysqltest1; create user USER identified via mysql_native_password as password("GOOD") OR unix_socket; create user mysqltest1 identified via mysql_native_password as password("good") OR unix_socket; @@ -29,6 +30,7 @@ select user(), current_user(), database(); user() current_user() database() mysqltest1@localhost mysqltest1@% test # name does not match, password bad = failure +mysqltest: Could not open connection 'default': 1698 Access denied for user 'mysqltest1'@'localhost' drop user USER, mysqltest1; create user USER identified via unix_socket OR ed25519 as password("GOOD"); create user mysqltest1 identified via unix_socket OR ed25519 as password("good"); @@ -44,6 +46,7 @@ select user(), current_user(), database(); user() current_user() database() mysqltest1@localhost mysqltest1@% test # name does not match, password bad = failure +mysqltest: Could not open connection 'default': 1045 Access denied for user 'mysqltest1'@'localhost' (using password: YES) drop user USER, mysqltest1; create user USER identified via ed25519 as password("GOOD") OR unix_socket; create user mysqltest1 identified via ed25519 as password("good") OR unix_socket; @@ -59,6 +62,7 @@ select user(), current_user(), database(); user() current_user() database() mysqltest1@localhost mysqltest1@% test # name does not match, password bad = failure +mysqltest: Could not open connection 'default': 1698 Access denied for user 'mysqltest1'@'localhost' drop user USER, mysqltest1; create user USER identified via ed25519 as password("GOOD") OR unix_socket OR mysql_native_password as password("works"); create user mysqltest1 identified via ed25519 as password("good") OR unix_socket OR mysql_native_password as password("works"); @@ -78,6 +82,7 @@ select user(), current_user(), database(); user() current_user() database() mysqltest1@localhost mysqltest1@% test # name does not match, password bad = failure +mysqltest: Could not open connection 'default': 1045 Access denied for user 'mysqltest1'@'localhost' (using password: YES) drop user USER, mysqltest1; create user mysqltest1 identified via mysql_native_password as password("good") OR mysql_native_password as password("works"); show create user mysqltest1; @@ -92,6 +97,7 @@ select user(), current_user(), database(); user() current_user() database() mysqltest1@localhost mysqltest1@% test # password bad = failure +mysqltest: Could not open connection 'default': 1045 Access denied for user 'mysqltest1'@'localhost' (using password: YES) drop user mysqltest1; create user mysqltest1 identified via ed25519 as password("good") OR unix_socket OR mysql_native_password as password("works"); show grants for mysqltest1; @@ -160,11 +166,29 @@ select user(), current_user(), database(); user() current_user() database() USER@localhost USER@% test # name does not match = failure +mysqltest: Could not open connection 'default': 1698 Access denied for user 'mysqltest1'@'localhost' # SET PASSWORD helps set password for mysqltest1 = password('bla'); select user(), current_user(), database(); user() current_user() database() mysqltest1@localhost mysqltest1@% test drop user USER, mysqltest1; +create user mysqltest1 identified via ed25519 as password("good"); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA ed25519 USING 'F4aF8bw7130VaRbdLCl4f/P/wkjDmgJXwWvpJ5gmsZc' +# no plugin = failure +mysqltest: Could not open connection 'default': 1045 Plugin client_ed25519 could not be loaded: /no/client_ed25519.so: cannot open shared object file: No such file or directory +alter user mysqltest1 identified via ed25519 as password("good") OR mysql_native_password as password("works"); +show create user mysqltest1; +CREATE USER for mysqltest1@% +CREATE USER 'mysqltest1'@'%' IDENTIFIED VIA ed25519 USING 'F4aF8bw7130VaRbdLCl4f/P/wkjDmgJXwWvpJ5gmsZc' OR mysql_native_password USING '*7D8C3DF236D9163B6C274A9D47704BC496988460' +# no plugin = failure +mysqltest: Could not open connection 'default': 1045 Access denied for user 'mysqltest1'@'localhost' (using password: YES) +# no plugin, second password works = ok +select user(), current_user(), database(); +user() current_user() database() +mysqltest1@localhost mysqltest1@% test +drop user mysqltest1; uninstall soname 'auth_socket'; uninstall soname 'auth_ed25519'; diff --git a/mysql-test/suite/plugins/t/multiauth.test b/mysql-test/suite/plugins/t/multiauth.test index cb86b4ea2f0..083fefd6756 100644 --- a/mysql-test/suite/plugins/t/multiauth.test +++ b/mysql-test/suite/plugins/t/multiauth.test @@ -13,7 +13,7 @@ if (!$AUTH_ED25519_SO) { install soname 'auth_socket'; install soname 'auth_ed25519'; ---let $try_auth=$MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/peercred_test.txt +--let $try_auth=$MYSQL_TEST < $MYSQLTEST_VARDIR/tmp/peercred_test.txt 2>&1 --write_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt --let $replace1=$USER@localhost @@ -174,6 +174,24 @@ set password for mysqltest1 = password('bla'); --replace_result $dreplace "drop user USER" eval $dreplace, mysqltest1; +# +# missing client-side plugin +# +create user mysqltest1 identified via ed25519 as password("good"); +show create user mysqltest1; +--echo # no plugin = failure +--replace_result $plugindir +--error 1 +--exec $try_auth -u mysqltest1 -pgood --plugin-dir=$plugindir/no +alter user mysqltest1 identified via ed25519 as password("good") OR mysql_native_password as password("works"); +show create user mysqltest1; +--echo # no plugin = failure +--error 1 +--exec $try_auth -u mysqltest1 -pgood --plugin-dir=$plugindir/no +--echo # no plugin, second password works = ok +--exec $try_auth -u mysqltest1 -pworks --plugin-dir=$plugindir/no +drop user mysqltest1; + uninstall soname 'auth_socket'; uninstall soname 'auth_ed25519'; --remove_file $MYSQLTEST_VARDIR/tmp/peercred_test.txt From e33daef4466c9d901074c474d1ef65b67ba16eee Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 6 Feb 2019 08:35:48 +1100 Subject: [PATCH 37/91] Don't retry on close According to close(2) "Retrying the close() after a failure return is the wrong thing to do" Corrects 5c81cb880a054f34803e2821489533274ebf6c4e in MDEV-15635 --- mysys/my_fopen.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 59baeaec744..fbd84049700 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -171,10 +171,7 @@ int my_fclose(FILE *fd, myf MyFlags) my_file_info[file].type= UNOPEN; } #ifndef _WIN32 - do - { - err= fclose(fd); - } while (err == -1 && errno == EINTR); + err= fclose(fd); #else err= my_win_fclose(fd); #endif From 129b2dcef3c205266bf685be470894656beb2ec8 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 6 Feb 2019 16:12:12 +0200 Subject: [PATCH 38/91] Changed user_variables and sql_sequence to maturity state stable --- plugin/user_variables/mysql-test/user_variables/basic.result | 2 +- plugin/user_variables/user_variables.cc | 2 +- sql/ha_sequence.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin/user_variables/mysql-test/user_variables/basic.result b/plugin/user_variables/mysql-test/user_variables/basic.result index 5650fa0dcce..a4d01957830 100644 --- a/plugin/user_variables/mysql-test/user_variables/basic.result +++ b/plugin/user_variables/mysql-test/user_variables/basic.result @@ -7,7 +7,7 @@ PLUGIN_AUTHOR Sergey Vojtovich PLUGIN_DESCRIPTION User-defined variables PLUGIN_LICENSE GPL LOAD_OPTION ON -PLUGIN_MATURITY Gamma +PLUGIN_MATURITY Stable SHOW CREATE TABLE INFORMATION_SCHEMA.USER_VARIABLES; Table Create Table user_variables CREATE TEMPORARY TABLE `user_variables` ( diff --git a/plugin/user_variables/user_variables.cc b/plugin/user_variables/user_variables.cc index 80bf58612b5..8d7fe038bbd 100644 --- a/plugin/user_variables/user_variables.cc +++ b/plugin/user_variables/user_variables.cc @@ -135,6 +135,6 @@ maria_declare_plugin(user_variables) NULL, NULL, "1.0", - MariaDB_PLUGIN_MATURITY_GAMMA + MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index a199892f971..65bb0daf8cf 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -443,6 +443,6 @@ maria_declare_plugin(sql_sequence) NULL, /* status variables */ NULL, /* system variables */ "1.0", /* string version */ - MariaDB_PLUGIN_MATURITY_ALPHA /* maturity */ + MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ } maria_declare_plugin_end; From 8bee13da81aceb1948fad5547e5ec5a746bba0fc Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 6 Feb 2019 20:41:38 +0200 Subject: [PATCH 39/91] Added generated wsrep_xxx files to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 6f093a3612b..b6acd58bab0 100644 --- a/.gitignore +++ b/.gitignore @@ -128,6 +128,8 @@ scripts/wsrep_sst_mysqldump scripts/wsrep_sst_rsync scripts/wsrep_sst_rsync_wan scripts/wsrep_sst_mariabackup +scripts/wsrep_sst_xtrabackup +scripts/wsrep_sst_xtrabackup-v2 scripts/maria_add_gis_sp.sql scripts/maria_add_gis_sp_bootstrap.sql scripts/galera_new_cluster From d0799a04791588ba7f89f59516475c25947034e2 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 6 Feb 2019 20:42:15 +0200 Subject: [PATCH 40/91] Removed compiler warnings from tokudb - Backport from 10.4 --- storage/tokudb/tokudb_sysvars.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage/tokudb/tokudb_sysvars.cc b/storage/tokudb/tokudb_sysvars.cc index 1e841f3b959..0880322d435 100644 --- a/storage/tokudb/tokudb_sysvars.cc +++ b/storage/tokudb/tokudb_sysvars.cc @@ -892,6 +892,7 @@ static MYSQL_THDVAR_ULONGLONG( 1); #endif // defined(TOKU_INCLUDE_RFR) && TOKU_INCLUDE_RFR +#if defined(TOKU_INCLUDE_UPSERT) static MYSQL_THDVAR_BOOL( enable_fast_update, PLUGIN_VAR_THDLOCAL, @@ -907,6 +908,7 @@ static MYSQL_THDVAR_BOOL( NULL, NULL, false); +#endif #if TOKU_INCLUDE_XA static MYSQL_THDVAR_BOOL( From 4eae9eeccc4dc5301a5a1b53d1de0b33271fe1ce Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 6 Feb 2019 20:43:28 +0200 Subject: [PATCH 41/91] Backport BUILD scripts from 10.4 - Fixes building with galera and tokudb - Added support for --without-wsrep BUILD script option --- BUILD/SETUP.sh | 5 ++++- cmake/configure.pl | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index e9bede9c746..7e6f0831423 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -122,7 +122,8 @@ get_make_parallel_flag # SSL library to use.--with-ssl will select our bundled yaSSL # implementation of SSL. --with-ssl=yes will first try system library # then the boundled one --with-ssl=system will use the system library. -SSL_LIBRARY=--with-ssl=system +# We use bundled by default as this is guaranteed to work with Galera +SSL_LIBRARY=--with-ssl if [ "x$warning_mode" = "xpedantic" ]; then warnings="-W -Wall -ansi -pedantic -Wno-long-long -Wno-unused -D_POSIX_SOURCE" @@ -194,6 +195,8 @@ base_configs="$base_configs --with-extra-charsets=complex " base_configs="$base_configs --enable-thread-safe-client " base_configs="$base_configs --with-big-tables $maintainer_mode" base_configs="$base_configs --with-plugin-aria --with-aria-tmp-tables" +# Following is to get tokudb to work +base_configs="$base_configs --with-jemalloc=NO" if test -d "$path/../cmd-line-utils/readline" then diff --git a/cmake/configure.pl b/cmake/configure.pl index c502a172a22..dfd961ee085 100644 --- a/cmake/configure.pl +++ b/cmake/configure.pl @@ -145,6 +145,11 @@ foreach my $option (@ARGV) $cmakeargs = $cmakeargs." -DPLUGIN_".uc($1)."=".uc($2); next; } + if($option =~ /without-wsrep/) + { + $cmakeargs = $cmakeargs." -DWITH_WSREP=OFF"; + next; + } if($option =~ /with-zlib-dir=bundled/) { $cmakeargs = $cmakeargs." -DWITH_ZLIB=bundled"; @@ -185,6 +190,16 @@ foreach my $option (@ARGV) $cmakeargs = $cmakeargs." -DCMAKE_BUILD_TYPE=Debug -DSECURITY_HARDENED=OFF"; next; } + if($option =~ /with-(.*)=(.*)/) + { + $cmakeargs = $cmakeargs. " -DWITH_" . uc($1) . "=" . uc($2); + next; + } + if($option =~ /without-(.*)=(.*)/) + { + $cmakeargs = $cmakeargs. " -DWITHOUT_" . uc($1) . "=" . uc($2); + next; + } if($option =~ /prefix=/) { $cmake_install_prefix= substr($option, 7); From 16327fc2e76e9215059894b461e8aca7f989da00 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 9 Oct 2018 02:36:09 -0700 Subject: [PATCH 42/91] MDEV-17096 Pushdown of simple derived tables to storage engines MDEV-17631 select_handler for a full query pushdown Interfaces + Proof of Concept for federatedx with test cases. The interfaces have been developed for integration of ColumnStore engine. --- libmysqld/CMakeLists.txt | 3 +- .../federatedx_create_handlers.result | 202 +++++++++++++ .../federated/federatedx_create_handlers.test | 116 ++++++++ sql/CMakeLists.txt | 2 +- sql/derived_handler.cc | 84 ++++++ sql/derived_handler.h | 61 ++++ sql/handler.h | 17 ++ sql/select_handler.cc | 145 ++++++++++ sql/select_handler.h | 48 +++ sql/sql_derived.cc | 82 +++++- sql/sql_explain.cc | 28 +- sql/sql_explain.h | 2 + sql/sql_lex.cc | 13 +- sql/sql_lex.h | 10 +- sql/sql_select.cc | 75 ++++- sql/sql_select.h | 46 ++- sql/table.h | 7 + storage/federatedx/federatedx_pushdown.cc | 273 ++++++++++++++++++ storage/federatedx/federatedx_pushdown.h | 63 ++++ storage/federatedx/ha_federatedx.cc | 13 +- storage/federatedx/ha_federatedx.h | 9 + 21 files changed, 1279 insertions(+), 20 deletions(-) create mode 100644 mysql-test/suite/federated/federatedx_create_handlers.result create mode 100644 mysql-test/suite/federated/federatedx_create_handlers.test create mode 100644 sql/derived_handler.cc create mode 100644 sql/derived_handler.h create mode 100644 sql/select_handler.cc create mode 100644 sql/select_handler.h create mode 100644 storage/federatedx/federatedx_pushdown.cc create mode 100644 storage/federatedx/federatedx_pushdown.h diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 99b620882de..5936c4e43e3 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -77,7 +77,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/debug_sync.cc ../sql/opt_table_elimination.cc ../sql/sql_prepare.cc ../sql/sql_rename.cc ../sql/sql_repl.cc ../sql/sql_select.cc ../sql/sql_servers.cc - ../sql/group_by_handler.cc + ../sql/group_by_handler.cc ../sql/derived_handler.cc + ../sql/select_handler.cc ../sql/sql_show.cc ../sql/sql_state.c ../sql/sql_statistics.cc ../sql/sql_string.cc ../sql/sql_tablespace.cc ../sql/sql_table.cc ../sql/sql_test.cc diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result new file mode 100644 index 00000000000..fdad44c1b95 --- /dev/null +++ b/mysql-test/suite/federated/federatedx_create_handlers.result @@ -0,0 +1,202 @@ +connect master,127.0.0.1,root,,test,$MASTER_MYPORT,; +connect slave,127.0.0.1,root,,test,$SLAVE_MYPORT,; +connection master; +CREATE DATABASE federated; +connection slave; +CREATE DATABASE federated; +connection slave; +DROP TABLE IF EXISTS federated.t1; +Warnings: +Note 1051 Unknown table 'federated.t1' +CREATE TABLE federated.t1 ( +id int(20) NOT NULL, +name varchar(16) NOT NULL default '' +) +DEFAULT CHARSET=latin1; +INSERT INTO federated.t1 VALUES +(3,'xxx'), (7,'yyy'), (4,'xxx'), (1,'zzz'), (5,'yyy'); +DROP TABLE IF EXISTS federated.t2; +Warnings: +Note 1051 Unknown table 'federated.t2' +CREATE TABLE federated.t2 ( +name varchar(16) NOT NULL default '' +) +DEFAULT CHARSET=latin1; +INSERT INTO federated.t2 VALUES +('yyy'), ('www'), ('yyy'), ('xxx'), ('www'), ('yyy'), ('www'); +connection master; +DROP TABLE IF EXISTS federated.t1; +Warnings: +Note 1051 Unknown table 'federated.t1' +CREATE TABLE federated.t1 ( +id int(20) NOT NULL, +name varchar(16) NOT NULL default '' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; +DROP TABLE IF EXISTS federated.t2; +Warnings: +Note 1051 Unknown table 'federated.t2' +CREATE TABLE federated.t2 ( +name varchar(16) NOT NULL default '' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t2'; +SELECT * FROM federated.t1; +id name +3 xxx +7 yyy +4 xxx +1 zzz +5 yyy +SELECT id FROM federated.t1 WHERE id < 5; +id +3 +4 +1 +SELECT count(*), name FROM federated.t1 WHERE id < 5 GROUP BY name; +count(*) name +2 xxx +1 zzz +SELECT * FROM federated.t1, federated.t2 +WHERE federated.t1.name = federated.t2.name; +id name name +7 yyy yyy +5 yyy yyy +7 yyy yyy +5 yyy yyy +3 xxx xxx +4 xxx xxx +7 yyy yyy +5 yyy yyy +SELECT * FROM federated.t1 LEFT JOIN federated.t2 +ON federated.t1.name = federated.t2.name +WHERE federated.t1.id > 1; +id name name +7 yyy yyy +5 yyy yyy +7 yyy yyy +5 yyy yyy +3 xxx xxx +4 xxx xxx +7 yyy yyy +5 yyy yyy +SELECT * FROM federated.t1 +WHERE id IN (SELECT count(*) FROM federated.t2 GROUP BY name); +id name +3 xxx +1 zzz +EXPLAIN +SELECT id FROM federated.t1 WHERE id < 5; +id select_type table type possible_keys key key_len ref rows Extra +1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL +EXPLAIN EXTENDED +SELECT id FROM federated.t1 WHERE id < 5; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL NULL +Warnings: +Note 1003 select `federated`.`t1`.`id` AS `id` from `federated`.`t1` where `federated`.`t1`.`id` < 5 +EXPLAIN FORMAT=JSON +SELECT id FROM federated.t1 WHERE id < 5; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "message": "Pushed select" + } + } +} +ANALYZE +SELECT id FROM federated.t1 WHERE id < 5; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL +ANALYZE FORMAT=JSON +SELECT id FROM federated.t1 WHERE id < 5; +ANALYZE +{ + "query_block": { + "select_id": 1, + "table": { + "message": "Pushed select" + } + } +} +CREATE TABLE federated.t3 ( +name varchar(16) NOT NULL default '' +) +DEFAULT CHARSET=latin1; +INSERT INTO federated.t3 VALUES +('yyy'), ('www'), ('yyy'), ('xxx'), ('www'), ('yyy'), ('www'); +SELECT * +FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t +WHERE federated.t3.name=t.name; +name id name +yyy 5 yyy +yyy 7 yyy +yyy 5 yyy +yyy 7 yyy +xxx 4 xxx +yyy 5 yyy +yyy 7 yyy +EXPLAIN +SELECT * +FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t +WHERE federated.t3.name=t.name; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 7 +1 PRIMARY ref key0 key0 18 federated.t3.name 2 +2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL +EXPLAIN FORMAT=JSON +SELECT * +FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t +WHERE federated.t3.name=t.name; +EXPLAIN +{ + "query_block": { + "select_id": 1, + "table": { + "table_name": "t3", + "access_type": "ALL", + "rows": 7, + "filtered": 100 + }, + "table": { + "table_name": "", + "access_type": "ref", + "possible_keys": ["key0"], + "key": "key0", + "key_length": "18", + "used_key_parts": ["name"], + "ref": ["federated.t3.name"], + "rows": 2, + "filtered": 100, + "materialized": { + "query_block": { + "select_id": 2, + "table": { + "message": "Pushed derived" + } + } + } + } + } +} +ANALYZE +SELECT * +FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t +WHERE federated.t3.name=t.name; +id select_type table type possible_keys key key_len ref rows r_rows filtered r_filtered Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 7 7.00 100.00 100.00 +1 PRIMARY ref key0 key0 18 federated.t3.name 2 0.00 100.00 100.00 +2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL +DROP TABLE federated.t1, federated.t2; +connection slave; +DROP TABLE federated.t1, federated.t2; +connection default; +connection master; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; +connection slave; +DROP TABLE IF EXISTS federated.t1; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test new file mode 100644 index 00000000000..0e586dad0c1 --- /dev/null +++ b/mysql-test/suite/federated/federatedx_create_handlers.test @@ -0,0 +1,116 @@ +--source have_federatedx.inc +--source include/federated.inc + +connection slave; + +DROP TABLE IF EXISTS federated.t1; + +CREATE TABLE federated.t1 ( + id int(20) NOT NULL, + name varchar(16) NOT NULL default '' +) +DEFAULT CHARSET=latin1; + +INSERT INTO federated.t1 VALUES + (3,'xxx'), (7,'yyy'), (4,'xxx'), (1,'zzz'), (5,'yyy'); + +DROP TABLE IF EXISTS federated.t2; + +CREATE TABLE federated.t2 ( + name varchar(16) NOT NULL default '' +) +DEFAULT CHARSET=latin1; + +INSERT INTO federated.t2 VALUES + ('yyy'), ('www'), ('yyy'), ('xxx'), ('www'), ('yyy'), ('www'); + + +connection master; + +DROP TABLE IF EXISTS federated.t1; + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval +CREATE TABLE federated.t1 ( + id int(20) NOT NULL, + name varchar(16) NOT NULL default '' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; + +DROP TABLE IF EXISTS federated.t2; + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval +CREATE TABLE federated.t2 ( + name varchar(16) NOT NULL default '' +) +ENGINE="FEDERATED" DEFAULT CHARSET=latin1 +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t2'; + +SELECT * FROM federated.t1; + +SELECT id FROM federated.t1 WHERE id < 5; + +SELECT count(*), name FROM federated.t1 WHERE id < 5 GROUP BY name; + +SELECT * FROM federated.t1, federated.t2 + WHERE federated.t1.name = federated.t2.name; + +SELECT * FROM federated.t1 LEFT JOIN federated.t2 + ON federated.t1.name = federated.t2.name + WHERE federated.t1.id > 1; + +SELECT * FROM federated.t1 + WHERE id IN (SELECT count(*) FROM federated.t2 GROUP BY name); + +EXPLAIN +SELECT id FROM federated.t1 WHERE id < 5; + +EXPLAIN EXTENDED +SELECT id FROM federated.t1 WHERE id < 5; + +EXPLAIN FORMAT=JSON +SELECT id FROM federated.t1 WHERE id < 5; + +ANALYZE +SELECT id FROM federated.t1 WHERE id < 5; + +ANALYZE FORMAT=JSON +SELECT id FROM federated.t1 WHERE id < 5; + +CREATE TABLE federated.t3 ( + name varchar(16) NOT NULL default '' +) +DEFAULT CHARSET=latin1; + +INSERT INTO federated.t3 VALUES + ('yyy'), ('www'), ('yyy'), ('xxx'), ('www'), ('yyy'), ('www'); + +SELECT * +FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t +WHERE federated.t3.name=t.name; + +EXPLAIN +SELECT * +FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t +WHERE federated.t3.name=t.name; + +EXPLAIN FORMAT=JSON +SELECT * +FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t +WHERE federated.t3.name=t.name; + +ANALYZE +SELECT * +FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t +WHERE federated.t3.name=t.name; + +DROP TABLE federated.t1, federated.t2; + +connection slave; +DROP TABLE federated.t1, federated.t2; + +connection default; + +source include/federated_cleanup.inc; diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 708c36a58b0..0c0851e5086 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -96,7 +96,7 @@ SET (SQL_SOURCE sql_partition.cc sql_plugin.cc sql_prepare.cc sql_rename.cc debug_sync.cc sql_repl.cc sql_select.cc sql_show.cc sql_state.c - group_by_handler.cc + group_by_handler.cc derived_handler.cc select_handler.cc sql_statistics.cc sql_string.cc lex_string.h sql_table.cc sql_test.cc sql_trigger.cc sql_udf.cc sql_union.cc sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc diff --git a/sql/derived_handler.cc b/sql/derived_handler.cc new file mode 100644 index 00000000000..561c18a5657 --- /dev/null +++ b/sql/derived_handler.cc @@ -0,0 +1,84 @@ +#include "mariadb.h" +#include "sql_priv.h" +#include "sql_select.h" +#include "derived_handler.h" + +void derived_handler::set_derived(TABLE_LIST *tbl) +{ + derived= tbl; + table= tbl->table; + unit= tbl->derived; + select= unit->first_select(); + tmp_table_param= select->next_select() ? + ((select_unit *)(unit->result))->get_tmp_table_param() : + &select->join->tmp_table_param; +} + +Pushdown_derived::Pushdown_derived(TABLE_LIST *tbl, derived_handler *h) + : derived(tbl), handler(h) +{ + is_analyze= handler->thd->lex->analyze_stmt; +} + +Pushdown_derived::~Pushdown_derived() +{ + delete handler; +} + +int Pushdown_derived::execute() +{ + int err; + THD *thd= handler->thd; + TABLE *table= handler->table; + TMP_TABLE_PARAM *tmp_table_param= handler->tmp_table_param; + + DBUG_ENTER("Pushdown_query::execute"); + + if ((err= handler->init_scan())) + goto error; + + if (is_analyze) + { + handler->end_scan(); + DBUG_RETURN(0); + } + + while (!(err= handler->next_row())) + { + if (unlikely(thd->check_killed())) + { + handler->end_scan(); + DBUG_RETURN(-1); + } + + if ((err= table->file->ha_write_tmp_row(table->record[0]))) + { + bool is_duplicate; + if (likely(!table->file->is_fatal_error(err, HA_CHECK_DUP))) + continue; // Distinct elimination + + if (create_internal_tmp_table_from_heap(thd, table, + tmp_table_param->start_recinfo, + &tmp_table_param->recinfo, + err, 1, &is_duplicate)) + DBUG_RETURN(1); + if (is_duplicate) + continue; + } + } + + if (err != 0 && err != HA_ERR_END_OF_FILE) + goto error; + + if ((err= handler->end_scan())) + goto error_2; + + DBUG_RETURN(0); + +error: + handler->end_scan(); +error_2: + handler->print_error(err, MYF(0)); + DBUG_RETURN(-1); // Error not sent to client +} + diff --git a/sql/derived_handler.h b/sql/derived_handler.h new file mode 100644 index 00000000000..c312a93a1f7 --- /dev/null +++ b/sql/derived_handler.h @@ -0,0 +1,61 @@ +#ifndef DERIVED_HANDLER_INCLUDED +#define DERIVED_HANDLER_INCLUDED + +#include "mariadb.h" +#include "sql_priv.h" + +class TMP_TABLE_PARAM; + +typedef class st_select_lex_unit SELECT_LEX_UNIT; + +class derived_handler +{ +public: + THD *thd; + handlerton *ht; + + TABLE_LIST *derived; + + /* + Temporary table where all results should be stored in record[0] + The table has a field for every item from the select list of + the specification of derived. + */ + TABLE *table; + + TMP_TABLE_PARAM *tmp_table_param; + + SELECT_LEX_UNIT *unit; + + SELECT_LEX *select; + + derived_handler(THD *thd_arg, handlerton *ht_arg) + : thd(thd_arg), ht(ht_arg), derived(0),table(0), tmp_table_param(0), + unit(0), select(0) {} + virtual ~derived_handler() {} + + /* + Functions to scan data. All these returns 0 if ok, error code in case + of error + */ + + /* Initialize the process of producing rows of the derived table */ + virtual int init_scan()= 0; + + /* + Put the next produced row of the derived in table->record[0] and return 0. + Return HA_ERR_END_OF_FILE if there are no more rows, return other error + number in case of fatal error. + */ + virtual int next_row()= 0; + + /* End prodicing rows */ + virtual int end_scan()=0; + + /* Report errors */ + virtual void print_error(int error, myf errflag)=0; + + void set_derived(TABLE_LIST *tbl); +}; + +#endif /* DERIVED_HANDLER_INCLUDED */ diff --git a/sql/handler.h b/sql/handler.h index 68a54cc207a..346dbd68cd9 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1183,6 +1183,8 @@ struct handler_iterator { class handler; class group_by_handler; +class derived_handler; +class select_handler; struct Query; typedef class st_select_lex SELECT_LEX; typedef struct st_order ORDER; @@ -1502,6 +1504,21 @@ struct handlerton */ group_by_handler *(*create_group_by)(THD *thd, Query *query); + /* + Create and return a derived_handler if the storage engine can execute + the derived table 'derived', otherwise return NULL. + In a general case 'derived' may contain tables not from the engine. + If the engine cannot handle or does not want to handle such pushed derived + the function create_group_by has to return NULL. + */ + derived_handler *(*create_derived)(THD *thd, TABLE_LIST *derived); + + /* + Create and return a select_handler if the storage engine can execute + the select statement 'select, otherwise return NULL + */ + select_handler *(*create_select) (THD *thd, SELECT_LEX *select); + /********************************************************************* Table discovery API. It allows the server to "discover" tables that exist in the storage diff --git a/sql/select_handler.cc b/sql/select_handler.cc new file mode 100644 index 00000000000..17475f4907d --- /dev/null +++ b/sql/select_handler.cc @@ -0,0 +1,145 @@ +#include "mariadb.h" +#include "sql_priv.h" +#include "sql_select.h" +#include "select_handler.h" + + +Pushdown_select::Pushdown_select(SELECT_LEX *sel, select_handler *h) + : select(sel), handler(h) +{ + is_analyze= handler->thd->lex->analyze_stmt; +} + +Pushdown_select::~Pushdown_select() +{ + delete handler; + select->select_h= NULL; +} + +bool Pushdown_select::init() +{ + List types; + TMP_TABLE_PARAM tmp_table_param; + THD *thd= handler->thd; + DBUG_ENTER("Pushdown_select::init"); + if (select->master_unit()->join_union_item_types(thd, types, 1)) + DBUG_RETURN(true); + tmp_table_param.init(); + tmp_table_param.field_count= types.elements; + + handler->table= create_tmp_table(thd, &tmp_table_param, types, + (ORDER *) 0, false, 0, + TMP_TABLE_ALL_COLUMNS, 1, + &empty_clex_str, true, false); + if (!handler->table) + DBUG_RETURN(true); + if (handler->table->fill_item_list(&result_columns)) + DBUG_RETURN(true); + DBUG_RETURN(false); +} + +bool Pushdown_select::send_result_set_metadata() +{ + THD *thd= handler->thd; + Protocol *protocol= thd->protocol; + DBUG_ENTER("Pushdown_select::send_result_set_metadata"); + +#ifdef WITH_WSREP + if (WSREP(thd) && thd->wsrep_retry_query) + { + WSREP_DEBUG("skipping select metadata"); + DBUG_RETURN(false); + } + #endif /* WITH_WSREP */ + if (protocol->send_result_set_metadata(&result_columns, + Protocol::SEND_NUM_ROWS | + Protocol::SEND_EOF)) + DBUG_RETURN(true); + + DBUG_RETURN(false); +} + +bool Pushdown_select::send_data() +{ + THD *thd= handler->thd; + Protocol *protocol= thd->protocol; + DBUG_ENTER("Pushdown_select::send_data"); + + if (thd->killed == ABORT_QUERY) + DBUG_RETURN(false); + + protocol->prepare_for_resend(); + if (protocol->send_result_set_row(&result_columns)) + { + protocol->remove_last_row(); + DBUG_RETURN(true); + } + + thd->inc_sent_row_count(1); + + if (thd->vio_ok()) + DBUG_RETURN(protocol->write()); + + DBUG_RETURN(false); +} + +bool Pushdown_select::send_eof() +{ + THD *thd= handler->thd; + DBUG_ENTER("Pushdown_select::send_eof"); + + /* + Don't send EOF if we're in error condition (which implies we've already + sent or are sending an error) + */ + if (thd->is_error()) + DBUG_RETURN(true); + ::my_eof(thd); + DBUG_RETURN(false); +} + +int Pushdown_select::execute() +{ + int err; + THD *thd= handler->thd; + + DBUG_ENTER("Pushdown_select::execute"); + + if ((err= handler->init_scan())) + goto error; + + if (is_analyze) + { + handler->end_scan(); + DBUG_RETURN(0); + } + + if (send_result_set_metadata()) + DBUG_RETURN(-1); + + while (!(err= handler->next_row())) + { + if (thd->check_killed() || send_data()) + { + handler->end_scan(); + DBUG_RETURN(-1); + } + } + + if (err != 0 && err != HA_ERR_END_OF_FILE) + goto error; + + if ((err= handler->end_scan())) + goto error_2; + + if (send_eof()) + DBUG_RETURN(-1); + + DBUG_RETURN(0); + +error: + handler->end_scan(); +error_2: + handler->print_error(err, MYF(0)); + DBUG_RETURN(-1); // Error not sent to client +} diff --git a/sql/select_handler.h b/sql/select_handler.h new file mode 100644 index 00000000000..3b1347efed6 --- /dev/null +++ b/sql/select_handler.h @@ -0,0 +1,48 @@ +#ifndef SELECT_HANDLER_INCLUDED +#define SELECT_HANDLER_INCLUDED + +#include "mariadb.h" +#include "sql_priv.h" + +class select_handler +{ + public: + THD *thd; + handlerton *ht; + + SELECT_LEX *select; + + /* + Temporary table where all results should be stored in record[0] + The table has a field for every item from the select_lex::item_list. + */ + TABLE *table; + + select_handler(THD *thd_arg, handlerton *ht_arg) + : thd(thd_arg), ht(ht_arg), table(0) {} + + virtual ~select_handler() {} + + /* + Functions to scan the select result set. + All these returns 0 if ok, error code in case of error. + */ + + /* Initialize the process of producing rows of result set */ + virtual int init_scan() = 0; + + /* + Put the next produced row of the result set in table->record[0] + and return 0. Return HA_ERR_END_OF_FILE if there are no more rows, + return other error number in case of fatal error. + */ + virtual int next_row() = 0; + + /* Finish scanning */ + virtual int end_scan() = 0; + + /* Report errors */ + virtual void print_error(int error, myf errflag) = 0; +}; + +#endif /* SELECT_HANDLER_INCLUDED */ diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index d65969d2160..9b17dd314f3 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -27,6 +27,7 @@ #include "unireg.h" #include "sql_derived.h" #include "sql_select.h" +#include "derived_handler.h" #include "sql_base.h" #include "sql_view.h" // check_duplicate_names #include "sql_acl.h" // SELECT_ACL @@ -384,9 +385,16 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_RETURN(FALSE); } - if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI || - thd->lex->sql_command == SQLCOM_DELETE_MULTI) - thd->save_prep_leaf_list= TRUE; + if ((derived->dt_handler= derived->find_derived_handler(thd))) + { + derived->change_refs_to_fields(); + derived->set_materialized_derived(); + DBUG_RETURN(FALSE); + } + + if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI || + thd->lex->sql_command == SQLCOM_DELETE_MULTI) + thd->save_prep_leaf_list= TRUE; arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test @@ -904,6 +912,19 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_RETURN(FALSE); } + if (derived->is_materialized_derived() && !derived->dt_handler) + derived->dt_handler= derived->find_derived_handler(thd); + if (derived->dt_handler) + { + if (!(derived->pushdown_derived= + new (thd->mem_root) Pushdown_derived(derived, derived->dt_handler))) + { + delete derived->dt_handler; + derived->dt_handler= NULL; + DBUG_RETURN(1); + } + } + lex->current_select= first_select; if (unit->is_unit_op()) @@ -1108,6 +1129,17 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) select_unit *derived_result= derived->derived_result; SELECT_LEX *save_current_select= lex->current_select; + if (derived->pushdown_derived) + { + int res; + if (unit->executed) + DBUG_RETURN(FALSE); + res= derived->pushdown_derived->execute(); + unit->executed= true; + delete derived->pushdown_derived; + DBUG_RETURN(res); + } + if (unit->executed && !derived_is_recursive && (unit->uncacheable & UNCACHEABLE_DEPENDENT)) { @@ -1404,3 +1436,47 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) thd->lex->current_select= save_curr_select; DBUG_RETURN(false); } + + +derived_handler *TABLE_LIST::find_derived_handler(THD *thd) +{ + if (!derived || is_recursive_with_table()) + return 0; + for (SELECT_LEX *sl= derived->first_select(); sl; sl= sl->next_select()) + { + if (!(sl->join)) + continue; + for (TABLE_LIST *tbl= sl->join->tables_list; tbl; tbl= tbl->next_local) + { + if (!tbl->table) + continue; + handlerton *ht= tbl->table->file->partition_ht(); + if (!ht->create_derived) + continue; + derived_handler *dh= ht->create_derived(thd, this); + if (dh) + { + dh->set_derived(this); + return dh; + } + } + } + return 0; +} + + +TABLE_LIST *TABLE_LIST::get_first_table() +{ + for (SELECT_LEX *sl= derived->first_select(); sl; sl= sl->next_select()) + { + if (!(sl->join)) + continue; + for (TABLE_LIST *tbl= sl->join->tables_list; tbl; tbl= tbl->next_local) + { + if (!tbl->table) + continue; + return tbl; + } + } + return 0; +} diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 1c45b05ccc5..b8d80c7c59c 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -34,6 +34,9 @@ const char *unit_operation_text[4]= "UNIT RESULT","UNION RESULT","INTERSECT RESULT","EXCEPT RESULT" }; +const char *pushed_derived_text= "PUSHED DERIVED"; +const char *pushed_select_text= "PUSHED SELECT"; + static void write_item(Json_writer *writer, Item *item); static void append_item_to_str(String *out, Item *item); @@ -334,6 +337,9 @@ int print_explain_row(select_result_sink *result, List item_list; Item *item; + if (!select_type[0]) + return 0; + item_list.push_back(new (mem_root) Item_int(thd, (int32) select_number), mem_root); item_list.push_back(new (mem_root) Item_string_sys(thd, select_type), @@ -746,7 +752,15 @@ int Explain_select::print_explain(Explain_query *query, THD *thd= output->thd; MEM_ROOT *mem_root= thd->mem_root; - if (message) + if (select_type == pushed_derived_text || select_type == pushed_select_text) + { + print_explain_message_line(output, explain_flags, is_analyze, + select_id /*select number*/, + select_type, + NULL, /* rows */ + NULL); + } + else if (message) { List item_list; Item *item_null= new (mem_root) Item_null(thd); @@ -869,14 +883,20 @@ void Explain_select::print_explain_json(Explain_query *query, bool started_cache= print_explain_json_cache(writer, is_analyze); - if (message) + if (message || + select_type == pushed_derived_text || + select_type == pushed_select_text) { writer->add_member("query_block").start_object(); writer->add_member("select_id").add_ll(select_id); add_linkage(writer); writer->add_member("table").start_object(); - writer->add_member("message").add_str(message); + writer->add_member("message").add_str(select_type == pushed_derived_text ? + "Pushed derived" : + select_type == pushed_select_text ? + "Pushed select" : + message); writer->end_object(); print_explain_json_for_children(query, writer, is_analyze); @@ -1205,7 +1225,7 @@ int Explain_table_access::print_explain(select_result_sink *output, uint8 explai { THD *thd= output->thd; MEM_ROOT *mem_root= thd->mem_root; - + List item_list; Item *item_null= new (mem_root) Item_null(thd); diff --git a/sql/sql_explain.h b/sql/sql_explain.h index 38250cc40ce..587ee53b3c8 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -328,6 +328,8 @@ public: ///////////////////////////////////////////////////////////////////////////// extern const char *unit_operation_text[4]; +extern const char *pushed_derived_text; +extern const char *pushed_select_text; /* Explain structure for a UNION. diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index bff6dfb0e05..87f50d41b31 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2354,6 +2354,7 @@ void st_select_lex::init_query() tvc= 0; in_tvc= false; versioned_tables= 0; + pushdown_select= 0; } void st_select_lex::init_select() @@ -4650,7 +4651,10 @@ void st_select_lex::set_explain_type(bool on_the_fly) if (master_unit()->thd->lex->first_select_lex() == this) { - type= is_primary ? "PRIMARY" : "SIMPLE"; + if (pushdown_select) + type= pushed_select_text; + else + type= is_primary ? "PRIMARY" : "SIMPLE"; } else { @@ -4659,7 +4663,11 @@ void st_select_lex::set_explain_type(bool on_the_fly) /* If we're a direct child of a UNION, we're the first sibling there */ if (linkage == DERIVED_TABLE_TYPE) { - if (is_uncacheable & UNCACHEABLE_DEPENDENT) + bool is_pushed_master_unit= master_unit()->derived && + master_unit()->derived->pushdown_derived; + if (is_pushed_master_unit) + type= pushed_derived_text; + else if (is_uncacheable & UNCACHEABLE_DEPENDENT) type= "LATERAL DERIVED"; else type= "DERIVED"; @@ -9458,3 +9466,4 @@ bool SELECT_LEX::make_unique_derived_name(THD *thd, LEX_CSTRING *alias) alias->str= thd->strmake(buff, alias->length); return !alias->str; } + diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 24788158d26..8fa28ff41c2 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -225,6 +225,8 @@ class Item_window_func; struct sql_digest_state; class With_clause; class my_var; +class select_handler; +class Pushdown_select; #define ALLOC_ROOT_SET 1024 @@ -812,11 +814,12 @@ protected: bool prepare_join(THD *thd, SELECT_LEX *sl, select_result *result, ulong additional_options, bool is_union_select); - bool join_union_item_types(THD *thd, List &types, uint count); bool join_union_type_handlers(THD *thd, class Type_holder *holders, uint count); bool join_union_type_attributes(THD *thd, class Type_holder *holders, uint count); +public: + bool join_union_item_types(THD *thd, List &types, uint count); public: // Ensures that at least all members used during cleanup() are initialized. st_select_lex_unit() @@ -1240,6 +1243,9 @@ public: table_value_constr *tvc; bool in_tvc; + select_handler *select_h; + Pushdown_select *pushdown_select; + /** System Versioning */ public: uint versioned_tables; @@ -1471,6 +1477,8 @@ public: Item_transformer transformer, uchar *arg); + select_handler *find_select_handler(THD *thd); + private: bool m_non_agg_field_used; bool m_agg_func_used; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3b927510c80..7c5287d8b4a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -64,6 +64,7 @@ #include "sys_vars_shared.h" #include "sp_head.h" #include "sp_rcontext.h" +#include "select_handler.h" /* A key part number that means we're using a fulltext scan. @@ -1437,7 +1438,13 @@ int JOIN::optimize() { int res= 0; join_optimization_state init_state= optimization_state; - if (optimization_state == JOIN::OPTIMIZATION_PHASE_1_DONE) + if (select_lex->pushdown_select) + { + if (!(select_options & SELECT_DESCRIBE)) + res= select_lex->pushdown_select->init(); + with_two_phase_optimization= false; + } + else if (optimization_state == JOIN::OPTIMIZATION_PHASE_1_DONE) res= optimize_stage2(); else { @@ -3934,7 +3941,6 @@ void JOIN::exec_inner() if (select_options & SELECT_DESCRIBE) select_describe(this, FALSE, FALSE, FALSE, (zero_result_cause?zero_result_cause:"No tables used")); - else { if (result->send_result_set_metadata(*columns_list, @@ -4033,7 +4039,8 @@ void JOIN::exec_inner() not the case. */ if (exec_const_order_group_cond.elements && - !(select_options & SELECT_DESCRIBE)) + !(select_options & SELECT_DESCRIBE) && + !select_lex->pushdown_select) { List_iterator_fast const_item_it(exec_const_order_group_cond); Item *cur_const_item; @@ -4060,6 +4067,11 @@ void JOIN::exec_inner() !table_count ? "No tables used" : NullS); DBUG_VOID_RETURN; } + else if (select_lex->pushdown_select) + { + error= select_lex->pushdown_select->execute(); + DBUG_VOID_RETURN; + } else { /* it's a const select, materialize it. */ @@ -4271,6 +4283,19 @@ mysql_select(THD *thd, } } + select_lex->select_h= select_lex->find_select_handler(thd); + if (select_lex->select_h) + { + if (!(select_lex->pushdown_select= + new (thd->mem_root) Pushdown_select(select_lex, + select_lex->select_h))) + { + delete select_lex->select_h; + select_lex->select_h= NULL; + DBUG_RETURN(TRUE); + } + } + if ((err= join->optimize())) { goto err; // 1 @@ -4292,8 +4317,15 @@ mysql_select(THD *thd, select_lex->where= join->conds_history; select_lex->having= join->having_history; } - + err: + + if (select_lex->pushdown_select) + { + delete select_lex->pushdown_select; + select_lex->pushdown_select= NULL; + } + if (free_join) { THD_STAGE_INFO(thd, stage_end); @@ -25681,6 +25713,7 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) DBUG_ENTER("mysql_explain_union"); bool res= 0; SELECT_LEX *first= unit->first_select(); + bool is_pushed_union= unit->derived && unit->derived->pushdown_derived; for (SELECT_LEX *sl= first; sl; sl= sl->next_select()) { @@ -25698,9 +25731,12 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) } if (!(res= unit->prepare(unit->derived, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE))) - res= unit->exec(); + { + if (!is_pushed_union) + res= unit->exec(); + } } - else + else { thd->lex->current_select= first; unit->set_limit(unit->global_parameters()); @@ -25716,6 +25752,13 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) first->options | thd->variables.option_bits | SELECT_DESCRIBE, result, unit, first); } + + if (unit->derived && unit->derived->pushdown_derived) + { + delete unit->derived->pushdown_derived; + unit->derived->pushdown_derived= NULL; + } + DBUG_RETURN(res || thd->is_error()); } @@ -27367,6 +27410,26 @@ Item *remove_pushed_top_conjuncts(THD *thd, Item *cond) return cond; } +select_handler *SELECT_LEX::find_select_handler(THD *thd) +{ + if (next_select()) + return 0; + if (master_unit()->outer_select()) + return 0; + for (TABLE_LIST *tbl= join->tables_list; tbl; tbl= tbl->next_local) + { + if (!tbl->table) + continue; + handlerton *ht= tbl->table->file->partition_ht(); + if (!ht->create_select) + continue; + select_handler *sh= ht->create_select(thd, this); + return sh; + } + return 0; +} + + /** @} (end of group Query_Optimizer) */ diff --git a/sql/sql_select.h b/sql/sql_select.h index 4140a0293f8..bca2387e1a0 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -2442,9 +2442,53 @@ public: ~Pushdown_query() { delete handler; } /* Function that calls the above scan functions */ - int execute(JOIN *join); + int execute(JOIN *); }; +class derived_handler; + +class Pushdown_derived: public Sql_alloc +{ +private: + bool is_analyze; +public: + TABLE_LIST *derived; + derived_handler *handler; + + Pushdown_derived(TABLE_LIST *tbl, derived_handler *h); + + ~Pushdown_derived(); + + int execute(); +}; + + +class select_handler; + + +class Pushdown_select: public Sql_alloc +{ +private: + bool is_analyze; + List result_columns; + bool send_result_set_metadata(); + bool send_data(); + bool send_eof(); + +public: + SELECT_LEX *select; + select_handler *handler; + + Pushdown_select(SELECT_LEX *sel, select_handler *h); + + ~Pushdown_select(); + + bool init(); + + int execute(); +}; + + bool test_if_order_compatible(SQL_I_List &a, SQL_I_List &b); int test_if_group_changed(List &list); int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort); diff --git a/sql/table.h b/sql/table.h index b75fa9074a4..33cf23b36b0 100644 --- a/sql/table.h +++ b/sql/table.h @@ -55,6 +55,8 @@ class Virtual_column_info; class Table_triggers_list; class TMP_TABLE_PARAM; class SEQUENCE; +class derived_handler; +class Pushdown_derived; /* Used to identify NESTED_JOIN structures within a join (applicable only to @@ -2118,6 +2120,8 @@ struct TABLE_LIST TABLE_LIST * next_with_rec_ref; bool is_derived_with_recursive_reference; bool block_handle_derived; + derived_handler *dt_handler; + Pushdown_derived *pushdown_derived; ST_SCHEMA_TABLE *schema_table; /* Information_schema table */ st_select_lex *schema_select_lex; /* @@ -2584,6 +2588,9 @@ struct TABLE_LIST } void set_lock_type(THD* thd, enum thr_lock_type lock); + derived_handler *find_derived_handler(THD *thd); + TABLE_LIST *get_first_table(); + private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); diff --git a/storage/federatedx/federatedx_pushdown.cc b/storage/federatedx/federatedx_pushdown.cc new file mode 100644 index 00000000000..bfe421c8ab2 --- /dev/null +++ b/storage/federatedx/federatedx_pushdown.cc @@ -0,0 +1,273 @@ +/* + Copyright (c) 2019 MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* !!! For inclusion into ha_federatedx.cc */ + +static derived_handler* +create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived) +{ + ha_federatedx_derived_handler* handler = NULL; + handlerton *ht= 0; + + SELECT_LEX_UNIT *unit= derived->derived; + + for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) + { + if (!(sl->join)) + return 0; + for (TABLE_LIST *tbl= sl->join->tables_list; tbl; tbl= tbl->next_local) + { + if (!tbl->table) + return 0; + if (!ht) + ht= tbl->table->file->partition_ht(); + else if (ht != tbl->table->file->partition_ht()) + return 0; + } + } + + handler= new ha_federatedx_derived_handler(thd, derived); + + return handler; +} + + +/* + Implementation class of the derived_handler interface for FEDERATEDX: + class implementation +*/ + +ha_federatedx_derived_handler::ha_federatedx_derived_handler(THD *thd, + TABLE_LIST *dt) + : derived_handler(thd, federatedx_hton), + share(NULL), txn(NULL), iop(NULL), stored_result(NULL) +{ + derived= dt; +} + +ha_federatedx_derived_handler::~ha_federatedx_derived_handler() {} + +int ha_federatedx_derived_handler::init_scan() +{ + char query_buff[4096]; + THD *thd; + int rc= 0; + + DBUG_ENTER("ha_federatedx_derived_handler::init_scan"); + + TABLE *table= derived->get_first_table()->table; + ha_federatedx *h= (ha_federatedx *) table->file; + iop= &h->io; + share= get_share(table->s->table_name.str, table); + thd= table->in_use; + txn= h->get_txn(thd); + if ((rc= txn->acquire(share, thd, TRUE, iop))) + DBUG_RETURN(rc); + + String derived_query(query_buff, sizeof(query_buff), thd->charset()); + derived_query.length(0); + derived->derived->print(&derived_query, QT_ORDINARY); + + if ((*iop)->query(derived_query.ptr(), derived_query.length())) + goto err; + + stored_result= (*iop)->store_result(); + if (!stored_result) + goto err; + + DBUG_RETURN(0); + +err: + DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM); +} + +int ha_federatedx_derived_handler::next_row() +{ + int rc; + FEDERATEDX_IO_ROW *row; + ulong *lengths; + Field **field; + int column= 0; + Time_zone *saved_time_zone= table->in_use->variables.time_zone; + DBUG_ENTER("ha_federatedx_derived_handler::next_row"); + + if ((rc= txn->acquire(share, table->in_use, TRUE, iop))) + DBUG_RETURN(rc); + + if (!(row= (*iop)->fetch_row(stored_result))) + DBUG_RETURN(HA_ERR_END_OF_FILE); + + /* Convert row to internal format */ + table->in_use->variables.time_zone= UTC; + lengths= (*iop)->fetch_lengths(stored_result); + + for (field= table->field; *field; field++, column++) + { + if ((*iop)->is_column_null(row, column)) + (*field)->set_null(); + else + { + (*field)->set_notnull(); + (*field)->store((*iop)->get_column_data(row, column), + lengths[column], &my_charset_bin); + } + } + table->in_use->variables.time_zone= saved_time_zone; + + DBUG_RETURN(rc); +} + +int ha_federatedx_derived_handler::end_scan() +{ + DBUG_ENTER("ha_federatedx_derived_handler::end_scan"); + + (*iop)->free_result(stored_result); + + free_share(txn, share); + + DBUG_RETURN(0); +} + +void ha_federatedx_derived_handler::print_error(int, unsigned long) +{ +} + + +static select_handler* +create_federatedx_select_handler(THD* thd, SELECT_LEX *sel) +{ + ha_federatedx_select_handler* handler = NULL; + handlerton *ht= 0; + + for (TABLE_LIST *tbl= thd->lex->query_tables; tbl; tbl= tbl->next_global) + { + if (!tbl->table) + return 0; + if (!ht) + ht= tbl->table->file->partition_ht(); + else if (ht != tbl->table->file->partition_ht()) + return 0; + } + + handler= new ha_federatedx_select_handler(thd, sel); + + return handler; +} + +/* + Implementation class of the select_handler interface for FEDERATEDX: + class implementation +*/ + +ha_federatedx_select_handler::ha_federatedx_select_handler(THD *thd, + SELECT_LEX *sel) + : select_handler(thd, federatedx_hton), + share(NULL), txn(NULL), iop(NULL), stored_result(NULL) +{ + select= sel; +} + +ha_federatedx_select_handler::~ha_federatedx_select_handler() {} + +int ha_federatedx_select_handler::init_scan() +{ + int rc= 0; + + DBUG_ENTER("ha_federatedx_select_handler::init_scan"); + + TABLE *table= 0; + for (TABLE_LIST *tbl= thd->lex->query_tables; tbl; tbl= tbl->next_global) + { + if (!tbl->table) + continue; + table= tbl->table; + break; + } + ha_federatedx *h= (ha_federatedx *) table->file; + iop= &h->io; + share= get_share(table->s->table_name.str, table); + txn= h->get_txn(thd); + if ((rc= txn->acquire(share, thd, TRUE, iop))) + DBUG_RETURN(rc); + + if ((*iop)->query(thd->query(), thd->query_length())) + goto err; + + stored_result= (*iop)->store_result(); + if (!stored_result) + goto err; + + DBUG_RETURN(0); + +err: + DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM); +} + +int ha_federatedx_select_handler::next_row() +{ + int rc= 0; + FEDERATEDX_IO_ROW *row; + ulong *lengths; + Field **field; + int column= 0; + Time_zone *saved_time_zone= table->in_use->variables.time_zone; + DBUG_ENTER("ha_federatedx_select_handler::next_row"); + + if ((rc= txn->acquire(share, table->in_use, TRUE, iop))) + DBUG_RETURN(rc); + + if (!(row= (*iop)->fetch_row(stored_result))) + DBUG_RETURN(HA_ERR_END_OF_FILE); + + /* Convert row to internal format */ + table->in_use->variables.time_zone= UTC; + lengths= (*iop)->fetch_lengths(stored_result); + + for (field= table->field; *field; field++, column++) + { + if ((*iop)->is_column_null(row, column)) + (*field)->set_null(); + else + { + (*field)->set_notnull(); + (*field)->store((*iop)->get_column_data(row, column), + lengths[column], &my_charset_bin); + } + } + table->in_use->variables.time_zone= saved_time_zone; + + DBUG_RETURN(rc); +} + +int ha_federatedx_select_handler::end_scan() +{ + DBUG_ENTER("ha_federatedx_derived_handler::end_scan"); + + free_tmp_table(thd, table); + table= 0; + + (*iop)->free_result(stored_result); + + free_share(txn, share); + + DBUG_RETURN(0); +} + +void ha_federatedx_select_handler::print_error(int, unsigned long) +{ +} + + diff --git a/storage/federatedx/federatedx_pushdown.h b/storage/federatedx/federatedx_pushdown.h new file mode 100644 index 00000000000..961571b972c --- /dev/null +++ b/storage/federatedx/federatedx_pushdown.h @@ -0,0 +1,63 @@ +/* + Copyright (c) 2019 MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "derived_handler.h" +#include "select_handler.h" + +/* + Implementation class of the derived_handler interface for FEDERATEDX: + class declaration +*/ + +class ha_federatedx_derived_handler: public derived_handler +{ +private: + FEDERATEDX_SHARE *share; + federatedx_txn *txn; + federatedx_io **iop; + FEDERATEDX_IO_RESULT *stored_result; + +public: + ha_federatedx_derived_handler(THD* thd_arg, TABLE_LIST *tbl); + ~ha_federatedx_derived_handler(); + int init_scan(); + int next_row(); + int end_scan(); + void print_error(int, unsigned long); +}; + + +/* + Implementation class of the select_handler interface for FEDERATEDX: + class declaration +*/ + +class ha_federatedx_select_handler: public select_handler +{ +private: + FEDERATEDX_SHARE *share; + federatedx_txn *txn; + federatedx_io **iop; + FEDERATEDX_IO_RESULT *stored_result; + +public: + ha_federatedx_select_handler(THD* thd_arg, SELECT_LEX *sel); + ~ha_federatedx_select_handler(); + int init_scan(); + int next_row(); + int end_scan(); + void print_error(int, unsigned long); +}; diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 74d547cb674..918fbef711a 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -319,6 +319,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "sql_analyse.h" // append_escaped() #include "sql_show.h" // append_identifier() #include "tztime.h" // my_tz_find() +#include "sql_select.h" #ifdef I_AM_PARANOID #define MIN_PORT 1023 @@ -401,6 +402,12 @@ static void init_federated_psi_keys(void) #define init_federated_psi_keys() /* no-op */ #endif /* HAVE_PSI_INTERFACE */ +handlerton* federatedx_hton; + +static derived_handler* +create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived); +static select_handler* +create_federatedx_select_handler(THD* thd, SELECT_LEX *sel); /* Initialize the federatedx handler. @@ -418,7 +425,7 @@ int federatedx_db_init(void *p) { DBUG_ENTER("federatedx_db_init"); init_federated_psi_keys(); - handlerton *federatedx_hton= (handlerton *)p; + federatedx_hton= (handlerton *)p; federatedx_hton->state= SHOW_OPTION_YES; /* Needed to work with old .frm files */ federatedx_hton->db_type= DB_TYPE_FEDERATED_DB; @@ -432,6 +439,8 @@ int federatedx_db_init(void *p) federatedx_hton->discover_table_structure= ha_federatedx::discover_assisted; federatedx_hton->create= federatedx_create_handler; federatedx_hton->flags= HTON_ALTER_NOT_SUPPORTED; + federatedx_hton->create_derived= create_federatedx_derived_handler; + federatedx_hton->create_select= create_federatedx_select_handler; if (mysql_mutex_init(fe_key_mutex_federatedx, &federatedx_mutex, MY_MUTEX_INIT_FAST)) @@ -3668,6 +3677,7 @@ err1: return error; } +#include "federatedx_pushdown.cc" struct st_mysql_storage_engine federatedx_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; @@ -3689,3 +3699,4 @@ maria_declare_plugin(federatedx) MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ } maria_declare_plugin_end; + diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h index 16a1944b172..c6af5f257ef 100644 --- a/storage/federatedx/ha_federatedx.h +++ b/storage/federatedx/ha_federatedx.h @@ -1,3 +1,5 @@ +#ifndef HA_FEDERATEDX_INCLUDED +#define HA_FEDERATEDX_INCLUDED /* Copyright (c) 2008, Patrick Galbraith All rights reserved. @@ -445,6 +447,9 @@ public: int external_lock(THD *thd, int lock_type); int reset(void); int free_result(void); + + friend class ha_federatedx_derived_handler; + friend class ha_federatedx_select_handler; }; extern const char ident_quote_char; // Character for quoting @@ -460,3 +465,7 @@ extern federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root, FEDERATEDX_SERVER *server); extern federatedx_io *instantiate_io_null(MEM_ROOT *server_root, FEDERATEDX_SERVER *server); + +#include "federatedx_pushdown.h" + +#endif /* HA_FEDERATEDX_INCLUDED */ From 10dac4293f39863552ce2ec8a28629882c92f4d9 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Tue, 5 Feb 2019 17:53:22 +0300 Subject: [PATCH 43/91] MDEV-18444 ROW_FORMAT=COMPRESSED unnecessarily requires NOCOPY for INSTANT operation instant_alter_column_possible(): allow non-rebuilding operations for ROW_FORMAT=COMPRESSED --- .../suite/innodb/r/instant_alter_bugs.result | 18 ++++++++++++++++++ .../suite/innodb/t/instant_alter_bugs.test | 18 ++++++++++++++++++ storage/innobase/handler/handler0alter.cc | 5 ++--- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result index 91298859e42..7326b9b7c6e 100644 --- a/mysql-test/suite/innodb/r/instant_alter_bugs.result +++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result @@ -128,3 +128,21 @@ HANDLER h READ `PRIMARY` PREV WHERE 0; pk f1 f2 f3 f4 f5 f6 f7 f8 filler HANDLER h CLOSE; DROP TABLE t1; +create table t ( +a varchar(9), +b int, +c int, +row_start bigint unsigned generated always as row start invisible, +row_end bigint unsigned generated always as row end invisible, +period for system_time (row_start, row_end) +) engine=innodb row_format=compressed with system versioning; +insert into t values (repeat('a', 9), 1, 1); +set @@system_versioning_alter_history = keep; +alter table t modify a varchar(10), algorithm=instant; +alter table t change b bb int, algorithm=instant; +alter table t modify c int without system versioning, algorithm=instant; +set @@system_versioning_alter_history = error; +check table t; +Table Op Msg_type Msg_text +test.t check status OK +drop table t; diff --git a/mysql-test/suite/innodb/t/instant_alter_bugs.test b/mysql-test/suite/innodb/t/instant_alter_bugs.test index 18ace4cc521..07d7db68c22 100644 --- a/mysql-test/suite/innodb/t/instant_alter_bugs.test +++ b/mysql-test/suite/innodb/t/instant_alter_bugs.test @@ -136,3 +136,21 @@ HANDLER h CLOSE; DROP TABLE t1; --let $datadir= `select @@datadir` --remove_file $datadir/test/load.data + + +create table t ( + a varchar(9), + b int, + c int, + row_start bigint unsigned generated always as row start invisible, + row_end bigint unsigned generated always as row end invisible, + period for system_time (row_start, row_end) +) engine=innodb row_format=compressed with system versioning; +insert into t values (repeat('a', 9), 1, 1); +set @@system_versioning_alter_history = keep; +alter table t modify a varchar(10), algorithm=instant; +alter table t change b bb int, algorithm=instant; +alter table t modify c int without system versioning, algorithm=instant; +set @@system_versioning_alter_history = error; +check table t; +drop table t; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 51d0042e011..38353554be4 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1465,9 +1465,6 @@ instant_alter_column_possible( const TABLE* table, const TABLE* altered_table) { - if (!ib_table.supports_instant()) { - return false; - } #if 1 // MDEV-17459: adjust fts_fetch_doc_from_rec() and friends; remove this if (ib_table.fts) { return false; @@ -1521,6 +1518,8 @@ instant_alter_column_possible( && alter_options_need_rebuild(ha_alter_info, table)) { return false; } + } else if (!ib_table.supports_instant()) { + return false; } /* At the moment, we disallow ADD [UNIQUE] INDEX together with From 0a1c3477bf359c55be3e11ec6502bc7b5bb87f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 6 Feb 2019 19:50:11 +0200 Subject: [PATCH 44/91] MDEV-18493 Remove page_size_t MySQL 5.7 introduced the class page_size_t and increased the size of buffer pool page descriptors by introducing this object to them. Maybe the intention of this exercise was to prepare for a future where the buffer pool could accommodate multiple page sizes. But that future never arrived, not even in MySQL 8.0. It is much easier to manage a pool of a single page size, and typically all storage devices of an InnoDB instance benefit from using the same page size. Let us remove page_size_t from MariaDB Server. This will make it easier to remove support for ROW_FORMAT=COMPRESSED (or make it a compile-time option) in the future, just by removing various occurrences of zip_size. --- extra/innochecksum.cc | 138 +++---- extra/mariabackup/fil_cur.cc | 32 +- extra/mariabackup/fil_cur.h | 7 +- extra/mariabackup/read_filt.cc | 2 +- extra/mariabackup/read_filt.h | 2 +- extra/mariabackup/write_filt.cc | 12 +- extra/mariabackup/xtrabackup.cc | 37 +- extra/mariabackup/xtrabackup.h | 9 +- storage/innobase/btr/btr0btr.cc | 115 +++--- storage/innobase/btr/btr0bulk.cc | 13 +- storage/innobase/btr/btr0cur.cc | 179 +++++---- storage/innobase/btr/btr0defragment.cc | 18 +- storage/innobase/btr/btr0pcur.cc | 2 +- storage/innobase/btr/btr0scrub.cc | 22 +- storage/innobase/btr/btr0sea.cc | 2 +- storage/innobase/buf/buf0buf.cc | 166 ++++----- storage/innobase/buf/buf0dblwr.cc | 82 ++-- storage/innobase/buf/buf0dump.cc | 8 +- storage/innobase/buf/buf0flu.cc | 11 +- storage/innobase/buf/buf0lru.cc | 70 ++-- storage/innobase/buf/buf0rea.cc | 99 ++--- storage/innobase/data/data0data.cc | 8 +- storage/innobase/dict/dict0boot.cc | 2 +- storage/innobase/dict/dict0crea.cc | 24 +- storage/innobase/dict/dict0dict.cc | 56 +-- storage/innobase/dict/dict0stats.cc | 4 +- storage/innobase/fil/fil0crypt.cc | 103 +++-- storage/innobase/fil/fil0fil.cc | 140 ++----- storage/innobase/fil/fil0pagecompress.cc | 3 +- storage/innobase/fsp/fsp0file.cc | 43 +-- storage/innobase/fsp/fsp0fsp.cc | 435 +++++++++------------- storage/innobase/fts/fts0fts.cc | 4 +- storage/innobase/fts/fts0que.cc | 8 +- storage/innobase/fut/fut0lst.cc | 64 ++-- storage/innobase/gis/gis0rtree.cc | 8 +- storage/innobase/gis/gis0sea.cc | 11 +- storage/innobase/handler/ha_innodb.cc | 20 +- storage/innobase/handler/handler0alter.cc | 2 +- storage/innobase/handler/i_s.cc | 13 +- storage/innobase/ibuf/ibuf0ibuf.cc | 311 ++++++++-------- storage/innobase/include/btr0btr.h | 57 ++- storage/innobase/include/btr0btr.ic | 14 +- storage/innobase/include/btr0cur.h | 16 +- storage/innobase/include/btr0types.h | 10 +- storage/innobase/include/buf0buf.h | 56 +-- storage/innobase/include/buf0rea.h | 37 +- storage/innobase/include/dict0dict.h | 34 +- storage/innobase/include/dict0dict.ic | 22 -- storage/innobase/include/fil0crypt.h | 41 +- storage/innobase/include/fil0fil.h | 59 ++- storage/innobase/include/fsp0fsp.h | 106 +++--- storage/innobase/include/fsp0fsp.ic | 69 +--- storage/innobase/include/fut0fut.h | 28 +- storage/innobase/include/fut0fut.ic | 68 ---- storage/innobase/include/ibuf0ibuf.h | 56 +-- storage/innobase/include/ibuf0ibuf.ic | 49 +-- storage/innobase/include/mem0mem.ic | 4 +- storage/innobase/include/os0file.h | 2 +- storage/innobase/include/page0size.h | 197 ---------- storage/innobase/include/page0zip.h | 15 +- storage/innobase/include/page0zip.ic | 21 +- storage/innobase/include/row0ext.h | 9 +- storage/innobase/include/trx0rseg.ic | 5 +- storage/innobase/include/trx0sys.h | 2 +- storage/innobase/include/trx0undo.ic | 8 +- storage/innobase/lock/lock0lock.cc | 2 +- storage/innobase/log/log0log.cc | 8 +- storage/innobase/log/log0recv.cc | 22 +- storage/innobase/mtr/mtr0mtr.cc | 2 +- storage/innobase/os/os0file.cc | 2 - storage/innobase/page/page0zip.cc | 17 +- storage/innobase/row/row0ext.cc | 32 +- storage/innobase/row/row0ftsort.cc | 4 +- storage/innobase/row/row0import.cc | 81 ++-- storage/innobase/row/row0log.cc | 18 +- storage/innobase/row/row0merge.cc | 17 +- storage/innobase/row/row0mysql.cc | 3 +- storage/innobase/row/row0purge.cc | 2 +- storage/innobase/row/row0row.cc | 4 +- storage/innobase/row/row0sel.cc | 16 +- storage/innobase/row/row0upd.cc | 39 +- storage/innobase/srv/srv0srv.cc | 2 - storage/innobase/srv/srv0start.cc | 13 +- storage/innobase/trx/trx0rec.cc | 34 +- storage/innobase/trx/trx0undo.cc | 8 +- 85 files changed, 1445 insertions(+), 2151 deletions(-) delete mode 100644 storage/innobase/include/fut0fut.ic delete mode 100644 storage/innobase/include/page0size.h diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index de640a17765..31826981ba3 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. - Copyright (c) 2014, 2018, MariaDB Corporation. + Copyright (c) 2014, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -71,10 +71,8 @@ static my_bool per_page_details; static ulint n_merge; extern ulong srv_checksum_algorithm; static ulint physical_page_size; /* Page size in bytes on disk. */ -static ulint logical_page_size; /* Page size when uncompressed. */ ulong srv_page_size; ulong srv_page_size_shift; -page_size_t univ_page_size(0, 0, false); /* Current page number (0 based). */ unsigned long long cur_page_num; /* Skip the checksum verification. */ @@ -276,13 +274,11 @@ void print_leaf_stats( } } -/** Get the page size of the filespace from the filespace header. +/** Get the ROW_FORMAT=COMPRESSED size from the filespace header. @param[in] buf buffer used to read the page. -@return page size */ -static -const page_size_t -get_page_size( - byte* buf) +@return ROW_FORMAT_COMPRESSED page size +@retval 0 if not ROW_FORMAT=COMPRESSED */ +static ulint get_zip_size(const byte* buf) { const unsigned flags = mach_read_from_4(buf + FIL_PAGE_DATA + FSP_SPACE_FLAGS); @@ -294,11 +290,14 @@ get_page_size( : UNIV_PAGE_SIZE_SHIFT_ORIG; srv_page_size = 1U << srv_page_size_shift; - - univ_page_size.copy_from( - page_size_t(srv_page_size, srv_page_size, false)); - - return(page_size_t(flags)); + ulint zip_size = FSP_FLAGS_GET_ZIP_SSIZE(flags); + if (zip_size) { + zip_size = (UNIV_ZIP_SIZE_MIN >> 1) << zip_size; + physical_page_size = zip_size; + } else { + physical_page_size = srv_page_size; + } + return zip_size; } #ifdef _WIN32 @@ -430,7 +429,7 @@ ulint read_file( /** Check if page is corrupted or not. @param[in] buf page frame -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] is_encrypted true if page0 contained cryp_data with crypt_scheme encrypted @param[in] is_compressed true if page0 fsp_flags contained @@ -440,7 +439,7 @@ static bool is_page_corrupted( byte* buf, - const page_size_t& page_size, + ulint zip_size, bool is_encrypted, bool is_compressed) { @@ -465,12 +464,12 @@ is_page_corrupted( return (false); } - if (page_size.is_compressed()) { + if (!zip_size) { /* check the stored log sequence numbers for uncompressed tablespace. */ logseq = mach_read_from_4(buf + FIL_PAGE_LSN + 4); logseqfield = mach_read_from_4( - buf + page_size.logical() - + buf + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM + 4); if (is_log_enabled) { @@ -499,8 +498,7 @@ is_page_corrupted( so if crypt checksum does not match we verify checksum using normal method. */ if (is_encrypted && key_version != 0) { - is_corrupted = !fil_space_verify_crypt_checksum(buf, - page_size); + is_corrupted = !fil_space_verify_crypt_checksum(buf, zip_size); if (is_corrupted && log_file) { fprintf(log_file, "Page " ULINTPF ":%llu may be corrupted;" @@ -516,7 +514,7 @@ is_page_corrupted( if (is_corrupted) { is_corrupted = buf_page_is_corrupted( - true, buf, page_size, NULL); + true, buf, zip_size, NULL); } return(is_corrupted); @@ -568,7 +566,6 @@ is_page_empty( /********************************************************************//** Rewrite the checksum for the page. @param [in/out] page page buffer -@param [in] physical_page_size page size in bytes on disk. @param [in] iscompressed Is compressed/Uncompressed Page. @retval true : do rewrite @@ -579,7 +576,6 @@ Rewrite the checksum for the page. bool update_checksum( byte* page, - ulong physical_page_size, bool iscompressed) { ib_uint32_t checksum = 0; @@ -696,7 +692,6 @@ func_exit: @param[in] compressed Enabled if tablespace is compressed. @param[in,out] pos current file position. -@param[in] page_size page size in bytes on disk. @retval true if successfully written @retval false if a non-recoverable error occurred @@ -708,12 +703,11 @@ write_file( FILE* file, byte* buf, bool compressed, - fpos_t* pos, - ulong page_size) + fpos_t* pos) { bool do_update; - do_update = update_checksum(buf, page_size, compressed); + do_update = update_checksum(buf, compressed); if (file != stdin) { if (do_update) { @@ -733,8 +727,9 @@ write_file( } } - if (page_size - != fwrite(buf, 1, page_size, file == stdin ? stdout : file)) { + if (physical_page_size + != fwrite(buf, 1, physical_page_size, + file == stdin ? stdout : file)) { fprintf(stderr, "Failed to write page::%llu to %s: %s\n", cur_page_num, filename, strerror(errno)); @@ -757,7 +752,6 @@ Parse the page and collect/dump the information about page type @param [in] page buffer page @param [out] xdes extend descriptor page @param [in] file file for diagnosis. -@param [in] page_size page_size @param [in] is_encrypted tablespace is encrypted */ void @@ -765,7 +759,6 @@ parse_page( const byte* page, byte* xdes, FILE* file, - const page_size_t& page_size, bool is_encrypted) { unsigned long long id; @@ -824,8 +817,7 @@ parse_page( } size_range_id = (data_bytes * SIZE_RANGES_FOR_PAGE - + page_size.logical() - 1) / - page_size.logical(); + + srv_page_size - 1) / srv_page_size; if (size_range_id > SIZE_RANGES_FOR_PAGE + 1) { /* data_bytes is bigger than logical_page_size */ @@ -844,7 +836,7 @@ parse_page( it = index_ids.find(id); per_index_stats &index = (it->second); const byte* des = xdes + XDES_ARR_OFFSET - + XDES_SIZE * ((page_no & (page_size.physical() - 1)) + + XDES_SIZE * ((page_no & (physical_page_size - 1)) / FSP_EXTENT_SIZE); if (xdes_get_bit(des, XDES_FREE_BIT, page_no % FSP_EXTENT_SIZE)) { @@ -1007,7 +999,7 @@ parse_page( case FIL_PAGE_TYPE_FSP_HDR: page_type.n_fil_page_type_fsp_hdr++; - memcpy(xdes, page, page_size.physical()); + memcpy(xdes, page, physical_page_size); if (page_type_dump) { fprintf(file, "#::%llu\t\t|\t\tFile Space " "Header\t\t|\t%s\n", cur_page_num, str); @@ -1016,7 +1008,7 @@ parse_page( case FIL_PAGE_TYPE_XDES: page_type.n_fil_page_type_xdes++; - memcpy(xdes, page, page_size.physical()); + memcpy(xdes, page, physical_page_size); if (page_type_dump) { fprintf(file, "#::%llu\t\t|\t\tExtent descriptor " "page\t\t|\t%s\n", cur_page_num, str); @@ -1384,18 +1376,13 @@ get_options( /** Check from page 0 if table is encrypted. @param[in] filename Filename -@param[in] page_size page size @param[in] page Page 0 @retval true if tablespace is encrypted, false if not */ -static -bool check_encryption( - const char* filename, - const page_size_t& page_size, - byte * page) +static bool check_encryption(const char* filename, const byte* page) { - ulint offset = (FSP_HEADER_OFFSET + (XDES_ARR_OFFSET + XDES_SIZE * - (page_size.physical()) / FSP_EXTENT_SIZE)); + ulint offset = FSP_HEADER_OFFSET + XDES_ARR_OFFSET + XDES_SIZE * + physical_page_size / FSP_EXTENT_SIZE; if (memcmp(page + offset, CRYPT_MAGIC, MAGIC_SZ) != 0) { return false; @@ -1431,7 +1418,7 @@ bool check_encryption( /** Verify page checksum. @param[in] buf page to verify -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] is_encrypted true if tablespace is encrypted @param[in] is_compressed true if tablespace is page compressed @param[in,out] mismatch_count Number of pages failed in checksum verify @@ -1440,7 +1427,7 @@ Verify page checksum. static int verify_checksum( byte* buf, - const page_size_t& page_size, + ulint zip_size, bool is_encrypted, bool is_compressed, unsigned long long* mismatch_count) @@ -1449,7 +1436,7 @@ int verify_checksum( bool is_corrupted = false; is_corrupted = is_page_corrupted( - buf, page_size, is_encrypted, is_compressed); + buf, zip_size, is_encrypted, is_compressed); if (is_corrupted) { fprintf(stderr, "Fail: page::%llu invalid\n", @@ -1477,7 +1464,7 @@ int verify_checksum( @param[in] filename File name @param[in] fil_in File pointer @param[in] buf page -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] pos File position @param[in] is_encrypted true if tablespace is encrypted @param[in] is_compressed true if tablespace is page compressed @@ -1488,7 +1475,7 @@ rewrite_checksum( const char* filename, FILE* fil_in, byte* buf, - const page_size_t& page_size, + ulint zip_size, fpos_t* pos, bool is_encrypted, bool is_compressed) @@ -1500,8 +1487,7 @@ rewrite_checksum( !is_encrypted && !is_compressed && !write_file(filename, fil_in, buf, - page_size.is_compressed(), pos, - static_cast(page_size.physical()))) { + zip_size, pos)) { exit_status = 1; } @@ -1682,22 +1668,19 @@ int main( /* Determine page size, zip_size and page compression from fsp_flags and encryption metadata from page 0 */ - const page_size_t& page_size = get_page_size(buf); + ulint zip_size = get_zip_size(buf); ulint flags = mach_read_from_4(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + buf); - ulint zip_size = page_size.is_compressed() ? page_size.logical() : 0; - logical_page_size = page_size.is_compressed() ? zip_size : 0; - physical_page_size = page_size.physical(); bool is_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(flags); - if (page_size.physical() > UNIV_ZIP_SIZE_MIN) { + if (physical_page_size > UNIV_ZIP_SIZE_MIN) { /* Read rest of the page 0 to determine crypt_data */ - bytes = read_file(buf, partial_page_read, page_size.physical(), fil_in); - if (bytes != page_size.physical()) { + bytes = read_file(buf, partial_page_read, physical_page_size, fil_in); + if (bytes != physical_page_size) { fprintf(stderr, "Error: Was not able to read the " "rest of the page "); fprintf(stderr, "of " ULINTPF " bytes. Bytes read was " ULINTPF "\n", - page_size.physical() - UNIV_ZIP_SIZE_MIN, bytes); + physical_page_size - UNIV_ZIP_SIZE_MIN, bytes); exit_status = 1; goto my_exit; @@ -1706,7 +1689,7 @@ int main( } /* Now that we have full page 0 in buffer, check encryption */ - bool is_encrypted = check_encryption(filename, page_size, buf); + bool is_encrypted = check_encryption(filename, buf); /* Verify page 0 contents. Note that we can't allow checksum mismatch on page 0, because that would mean we @@ -1715,7 +1698,7 @@ int main( unsigned long long tmp_allow_mismatches = allow_mismatches; allow_mismatches = 0; - exit_status = verify_checksum(buf, page_size, is_encrypted, is_compressed, &mismatch_count); + exit_status = verify_checksum(buf, zip_size, is_encrypted, is_compressed, &mismatch_count); if (exit_status) { fprintf(stderr, "Error: Page 0 checksum mismatch, can't continue. \n"); @@ -1725,7 +1708,7 @@ int main( } if ((exit_status = rewrite_checksum(filename, fil_in, buf, - page_size, &pos, is_encrypted, is_compressed))) { + zip_size, &pos, is_encrypted, is_compressed))) { goto my_exit; } @@ -1748,10 +1731,10 @@ int main( } if (page_type_summary || page_type_dump) { - parse_page(buf, xdes, fil_page_type, page_size, is_encrypted); + parse_page(buf, xdes, fil_page_type, is_encrypted); } - pages = (ulint) (size / page_size.physical()); + pages = (ulint) (size / physical_page_size); if (just_count) { if (read_from_stdin) { @@ -1788,12 +1771,9 @@ int main( partial_page_read = false; offset = (off_t) start_page - * (off_t) page_size.physical(); -#ifdef _WIN32 - if (_fseeki64(fil_in, offset, SEEK_SET)) { -#else - if (fseeko(fil_in, offset, SEEK_SET)) { -#endif /* _WIN32 */ + * (off_t) physical_page_size; + if (IF_WIN(_fseeki64,fseeko)(fil_in, offset, + SEEK_SET)) { perror("Error: Unable to seek to " "necessary offset"); @@ -1825,8 +1805,7 @@ int main( if partial_page_read is enable. */ bytes = read_file(buf, partial_page_read, - static_cast( - page_size.physical()), + physical_page_size, fil_in); partial_page_read = false; @@ -1851,8 +1830,7 @@ int main( while (!feof(fil_in)) { bytes = read_file(buf, partial_page_read, - static_cast( - page_size.physical()), fil_in); + physical_page_size, fil_in); partial_page_read = false; if (!bytes && feof(fil_in)) { @@ -1861,17 +1839,17 @@ int main( if (ferror(fil_in)) { fprintf(stderr, "Error reading " ULINTPF " bytes", - page_size.physical()); + physical_page_size); perror(" "); exit_status = 1; goto my_exit; } - if (bytes != page_size.physical()) { + if (bytes != physical_page_size) { fprintf(stderr, "Error: bytes read (" ULINTPF ") " "doesn't match page size (" ULINTPF ")\n", - bytes, page_size.physical()); + bytes, physical_page_size); exit_status = 1; goto my_exit; } @@ -1896,13 +1874,13 @@ int main( checksum verification.*/ if (!no_check && !skip_page - && (exit_status = verify_checksum(buf, page_size, + && (exit_status = verify_checksum(buf, zip_size, is_encrypted, is_compressed, &mismatch_count))) { goto my_exit; } if ((exit_status = rewrite_checksum(filename, fil_in, buf, - page_size, &pos, is_encrypted, is_compressed))) { + zip_size, &pos, is_encrypted, is_compressed))) { goto my_exit; } @@ -1916,7 +1894,7 @@ int main( } if (page_type_summary || page_type_dump) { - parse_page(buf, xdes, fil_page_type, page_size, is_encrypted); + parse_page(buf, xdes, fil_page_type, is_encrypted); } /* do counter increase and progress printing */ diff --git a/extra/mariabackup/fil_cur.cc b/extra/mariabackup/fil_cur.cc index f40304c07d7..04bf2b1f64d 100644 --- a/extra/mariabackup/fil_cur.cc +++ b/extra/mariabackup/fil_cur.cc @@ -231,11 +231,11 @@ xb_fil_cur_open( posix_fadvise(cursor->file, 0, 0, POSIX_FADV_SEQUENTIAL); - const page_size_t page_size(node->space->flags); - cursor->page_size = page_size; + cursor->page_size = node->space->physical_size(); + cursor->zip_size = node->space->zip_size(); /* Allocate read buffer */ - cursor->buf_size = XB_FIL_CUR_PAGES * page_size.physical(); + cursor->buf_size = XB_FIL_CUR_PAGES * cursor->page_size; cursor->orig_buf = static_cast (malloc(cursor->buf_size + srv_page_size)); cursor->buf = static_cast @@ -250,18 +250,17 @@ xb_fil_cur_open( if (!node->space->crypt_data && os_file_read(IORequestRead, node->handle, cursor->buf, 0, - page_size.physical())) { + cursor->page_size)) { mutex_enter(&fil_system.mutex); if (!node->space->crypt_data) { - node->space->crypt_data - = fil_space_read_crypt_data(page_size, - cursor->buf); + node->space->crypt_data = fil_space_read_crypt_data( + node->space->zip_size(), cursor->buf); } mutex_exit(&fil_system.mutex); } cursor->space_size = (ulint)(cursor->statinfo.st_size - / page_size.physical()); + / cursor->page_size); cursor->read_filter = read_filter; cursor->read_filter->init(&cursor->read_filter_ctxt, cursor, @@ -276,7 +275,7 @@ static bool page_is_corrupted(const byte *page, ulint page_no, { byte tmp_frame[UNIV_PAGE_SIZE_MAX]; byte tmp_page[UNIV_PAGE_SIZE_MAX]; - const ulint page_size = cursor->page_size.physical(); + const ulint page_size = cursor->page_size; ulint page_type = mach_read_from_2(page + FIL_PAGE_TYPE); /* We ignore the doublewrite buffer pages.*/ @@ -325,7 +324,7 @@ static bool page_is_corrupted(const byte *page, ulint page_no, || (space->crypt_data && space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED))) { - if (!fil_space_verify_crypt_checksum(page, cursor->page_size)) + if (!fil_space_verify_crypt_checksum(page, space->zip_size())) return true; /* Compressed encrypted need to be decrypted @@ -345,8 +344,7 @@ static bool page_is_corrupted(const byte *page, ulint page_no, } if (page_type != FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED) { - return buf_page_is_corrupted(true, tmp_page, - cursor->page_size, space); + return buf_page_is_corrupted(true, tmp_page, 0, space); } } @@ -361,14 +359,14 @@ static bool page_is_corrupted(const byte *page, ulint page_no, return (!decomp || (decomp != srv_page_size - && cursor->page_size.is_compressed()) + && cursor->zip_size) || page_type == FIL_PAGE_PAGE_COMPRESSED || page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED || buf_page_is_corrupted(true, tmp_page, - cursor->page_size, space)); + space->zip_size(), space)); } - return buf_page_is_corrupted(true, page, cursor->page_size, space); + return buf_page_is_corrupted(true, page, space->zip_size(), space); } /************************************************************************ @@ -389,7 +387,7 @@ xb_fil_cur_read( xb_fil_cur_result_t ret; ib_int64_t offset; ib_int64_t to_read; - const ulint page_size = cursor->page_size.physical(); + const ulint page_size = cursor->page_size; xb_ad(!cursor->is_system() || page_size == srv_page_size); cursor->read_filter->get_next_batch(&cursor->read_filter_ctxt, @@ -459,7 +457,7 @@ read_retry: "10 retries. File %s seems to be " "corrupted.", cursor->abs_path); ret = XB_FIL_CUR_ERROR; - buf_page_print(page, cursor->page_size); + ut_print_buf(stderr, page, page_size); break; } msg(cursor->thread_n, "Database page corruption detected at page " diff --git a/extra/mariabackup/fil_cur.h b/extra/mariabackup/fil_cur.h index ad023d93208..193c51d6c43 100644 --- a/extra/mariabackup/fil_cur.h +++ b/extra/mariabackup/fil_cur.h @@ -38,7 +38,9 @@ struct xb_fil_cur_t { char abs_path[FN_REFLEN]; /*!< absolute file path */ MY_STAT statinfo; /*!< information about the file */ - page_size_t page_size; /*!< page size */ + ulint zip_size; /*!< compressed page size in bytes or 0 + for uncompressed pages */ + ulint page_size; /*!< physical page size */ xb_read_filt_t* read_filter; /*!< read filter */ xb_read_filt_ctxt_t read_filter_ctxt; /*!< read filter context */ @@ -57,9 +59,6 @@ struct xb_fil_cur_t { ulint space_id; /*!< ID of tablespace */ ulint space_size; /*!< space size in pages */ - /** TODO: remove this default constructor */ - xb_fil_cur_t() : page_size(0), read_filter(0), read_filter_ctxt() {} - /** @return whether this is not a file-per-table tablespace */ bool is_system() const { diff --git a/extra/mariabackup/read_filt.cc b/extra/mariabackup/read_filt.cc index a48591abf29..055056245ba 100644 --- a/extra/mariabackup/read_filt.cc +++ b/extra/mariabackup/read_filt.cc @@ -127,7 +127,7 @@ rf_bitmap_get_next_batch( of pages */ { ulint start_page_id; - const ulint page_size = ctxt->page_size.physical(); + const ulint page_size = ctxt->page_size; start_page_id = (ulint)(ctxt->offset / page_size); diff --git a/extra/mariabackup/read_filt.h b/extra/mariabackup/read_filt.h index cebc714eed8..585662c7f9c 100644 --- a/extra/mariabackup/read_filt.h +++ b/extra/mariabackup/read_filt.h @@ -41,7 +41,7 @@ struct xb_read_filt_ctxt_t { /* Move these to union if any other filters are added in future */ xb_page_bitmap_range *bitmap_range; /*!< changed page bitmap range iterator for space_id */ - page_size_t page_size; /*!< page size */ + ulint page_size; /*!< page size */ ulint filter_batch_end;/*!< the ending page id of the current changed page block in the bitmap */ diff --git a/extra/mariabackup/write_filt.cc b/extra/mariabackup/write_filt.cc index 63b11850bfb..3332159f99b 100644 --- a/extra/mariabackup/write_filt.cc +++ b/extra/mariabackup/write_filt.cc @@ -75,8 +75,7 @@ wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name, ctxt->cursor = cursor; /* allocate buffer for incremental backup (4096 pages) */ - cp->delta_buf_size = (cursor->page_size.physical() / 4) - * cursor->page_size.physical(); + cp->delta_buf_size = (cursor->page_size / 4) * cursor->page_size; cp->delta_buf = (unsigned char *)os_mem_alloc_large(&cp->delta_buf_size); if (!cp->delta_buf) { @@ -88,7 +87,8 @@ wf_incremental_init(xb_write_filt_ctxt_t *ctxt, char *dst_name, /* write delta meta info */ snprintf(meta_name, sizeof(meta_name), "%s%s", dst_name, XB_DELTA_INFO_SUFFIX); - const xb_delta_info_t info(cursor->page_size, cursor->space_id); + const xb_delta_info_t info(cursor->page_size, cursor->zip_size, + cursor->space_id); if (!xb_write_delta_metadata(meta_name, &info)) { msg(cursor->thread_n,"Error: " "failed to write meta info for %s", @@ -116,8 +116,7 @@ wf_incremental_process(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile) ulint i; xb_fil_cur_t *cursor = ctxt->cursor; byte *page; - const ulint page_size - = cursor->page_size.physical(); + const ulint page_size = cursor->page_size; xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt); for (i = 0, page = cursor->buf; i < cursor->buf_npages; @@ -162,8 +161,7 @@ static my_bool wf_incremental_finalize(xb_write_filt_ctxt_t *ctxt, ds_file_t *dstfile) { xb_fil_cur_t *cursor = ctxt->cursor; - const ulint page_size - = cursor->page_size.physical(); + const ulint page_size = cursor->page_size; xb_wf_incremental_ctxt_t *cp = &(ctxt->u.wf_incremental_ctxt); if (cp->npages != page_size / 4) { diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 009a4891d93..8a107a408eb 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -1861,11 +1861,6 @@ static bool innodb_init_param() msg("innodb_data_file_path = %s", innobase_data_file_path); - /* This is the first time univ_page_size is used. - It was initialized to 16k pages before srv_page_size was set */ - univ_page_size.copy_from( - page_size_t(srv_page_size, srv_page_size, false)); - srv_sys_space.set_space_id(TRX_SYS_SPACE); srv_sys_space.set_name("innodb_system"); srv_sys_space.set_path(srv_data_home); @@ -2173,8 +2168,7 @@ xb_read_delta_metadata(const char *filepath, xb_delta_info_t *info) msg("page_size is required in %s", filepath); r = FALSE; } else { - info->page_size = page_size_t(zip_size ? zip_size : page_size, - page_size, zip_size != 0); + info->page_size = zip_size ? zip_size : page_size; } if (info->space_id == ULINT_UNDEFINED) { @@ -2202,9 +2196,8 @@ xb_write_delta_metadata(const char *filename, const xb_delta_info_t *info) "page_size = " ULINTPF "\n" "zip_size = " ULINTPF " \n" "space_id = " ULINTPF "\n", - info->page_size.logical(), - info->page_size.is_compressed() - ? info->page_size.physical() : 0, + info->page_size, + info->zip_size, info->space_id); len = strlen(buf); @@ -3107,7 +3100,7 @@ xb_load_single_table_tablespace( ut_a(node_size != (os_offset_t) -1); - n_pages = node_size / page_size_t(file->flags()).physical(); + n_pages = node_size / fil_space_t::physical_size(file->flags()); space = fil_space_create( name, file->space_id(), file->flags(), @@ -3312,7 +3305,7 @@ retry: } /* TRX_SYS page can't be compressed or encrypted. */ - if (buf_page_is_corrupted(false, page, univ_page_size)) { + if (buf_page_is_corrupted(false, page, 0)) { if (n_retries--) { os_thread_sleep(1000); goto retry; @@ -4590,16 +4583,15 @@ xb_space_create_file( fsp_header_init_fields(page, space_id, flags); mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id); - const page_size_t page_size(flags); + const ulint zip_size = fil_space_t::zip_size(flags); - if (!page_size.is_compressed()) { + if (!zip_size) { buf_flush_init_for_writing(NULL, page, NULL, 0); ret = os_file_write(IORequestWrite, path, *file, page, 0, srv_page_size); } else { page_zip_des_t page_zip; - ulint zip_size = page_size.physical(); page_zip_set_size(&page_zip, zip_size); page_zip.data = page + srv_page_size; fprintf(stderr, "zip_size = " ULINTPF "\n", zip_size); @@ -4776,19 +4768,20 @@ exit: } /* No matching space found. create the new one. */ - const ulint flags = info.page_size.is_compressed() - ? get_bit_shift(info.page_size.physical() + const ulint flags = info.zip_size + ? get_bit_shift(info.page_size >> (UNIV_ZIP_SIZE_SHIFT_MIN - 1)) << FSP_FLAGS_POS_ZIP_SSIZE | FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS - | (info.page_size.logical() == UNIV_PAGE_SIZE_ORIG + | (srv_page_size == UNIV_PAGE_SIZE_ORIG ? 0 - : get_bit_shift(info.page_size.logical() + : get_bit_shift(srv_page_size >> (UNIV_ZIP_SIZE_SHIFT_MIN - 1)) << FSP_FLAGS_POS_PAGE_SSIZE) : FSP_FLAGS_PAGE_SSIZE(); - ut_ad(page_size_t(flags).equals_to(info.page_size)); + ut_ad(fil_space_t::zip_size(flags) == info.zip_size); + ut_ad(fil_space_t::physical_size(flags) == info.page_size); if (fil_space_create(dest_space_name, info.space_id, flags, FIL_TYPE_TABLESPACE, 0)) { @@ -4825,7 +4818,7 @@ xtrabackup_apply_delta( ulint page_in_buffer; ulint incremental_buffers = 0; - xb_delta_info_t info(univ_page_size, SRV_TMP_SPACE_ID); + xb_delta_info_t info(srv_page_size, 0, SRV_TMP_SPACE_ID); ulint page_size; ulint page_size_shift; byte* incremental_buffer_base = NULL; @@ -4863,7 +4856,7 @@ xtrabackup_apply_delta( goto error; } - page_size = info.page_size.physical(); + page_size = info.page_size; page_size_shift = get_bit_shift(page_size); msg("page size for %s is %zu bytes", src_path, page_size); diff --git a/extra/mariabackup/xtrabackup.h b/extra/mariabackup/xtrabackup.h index 90f5e28e2c7..767efe14b50 100644 --- a/extra/mariabackup/xtrabackup.h +++ b/extra/mariabackup/xtrabackup.h @@ -28,11 +28,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA struct xb_delta_info_t { - xb_delta_info_t(page_size_t page_size, ulint space_id) - : page_size(page_size), space_id(space_id) {} + xb_delta_info_t(ulint page_size, ulint zip_size, ulint space_id) + : page_size(page_size), zip_size(zip_size), space_id(space_id) {} - page_size_t page_size; - ulint space_id; + ulint page_size; + ulint zip_size; + ulint space_id; }; /* value of the --incremental option */ diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 1b3ea2eb487..29696f96aa0 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, 2018, MariaDB Corporation. +Copyright (c) 2014, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -225,7 +225,7 @@ btr_root_block_get( buf_block_t* block = btr_block_get( page_id_t(index->table->space_id, index->page), - page_size_t(index->table->space->flags), mode, + index->table->space->zip_size(), mode, index, mtr); if (!block) { @@ -363,7 +363,7 @@ btr_root_adjust_on_import( page_zip_des_t* page_zip; dict_table_t* table = index->table; const page_id_t page_id(table->space_id, index->page); - const page_size_t page_size(table->space->flags); + const ulint zip_size = table->space->zip_size(); DBUG_EXECUTE_IF("ib_import_trigger_corruption_3", return(DB_CORRUPTION);); @@ -372,7 +372,7 @@ btr_root_adjust_on_import( mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO); - block = btr_block_get(page_id, page_size, RW_X_LATCH, index, &mtr); + block = btr_block_get(page_id, zip_size, RW_X_LATCH, index, &mtr); page = buf_block_get_frame(block); page_zip = buf_block_get_page_zip(block); @@ -474,7 +474,7 @@ btr_page_alloc_for_ibuf( new_block = buf_page_get( page_id_t(index->table->space_id, node_addr.page), - page_size_t(index->table->space->flags), + index->table->space->zip_size(), RW_X_LATCH, mtr); new_page = buf_block_get_frame(new_block); @@ -928,7 +928,7 @@ btr_node_ptr_get_child( return btr_block_get( page_id_t(index->table->space_id, btr_node_ptr_get_child_page_no(node_ptr, offsets)), - page_size_t(index->table->space->flags), + index->table->space->zip_size(), RW_SX_LATCH, index, mtr); } @@ -1137,7 +1137,7 @@ btr_free_root_invalidate( /** Prepare to free a B-tree. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] index_id PAGE_INDEX_ID contents @param[in,out] mtr mini-transaction @return root block, to invoke btr_free_but_not_root() and btr_free_root() @@ -1146,7 +1146,7 @@ static MY_ATTRIBUTE((warn_unused_result)) buf_block_t* btr_free_root_check( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, index_id_t index_id, mtr_t* mtr) { @@ -1154,7 +1154,7 @@ btr_free_root_check( ut_ad(index_id != BTR_FREED_INDEX_ID); buf_block_t* block = buf_page_get( - page_id, page_size, RW_X_LATCH, mtr); + page_id, zip_size, RW_X_LATCH, mtr); if (block) { buf_block_dbg_add_level(block, SYNC_TREE_NODE); @@ -1368,18 +1368,18 @@ top_loop: /** Free a persistent index tree if it exists. @param[in] page_id root page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] index_id PAGE_INDEX_ID contents @param[in,out] mtr mini-transaction */ void btr_free_if_exists( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, index_id_t index_id, mtr_t* mtr) { buf_block_t* root = btr_free_root_check( - page_id, page_size, index_id, mtr); + page_id, zip_size, index_id, mtr); if (root == NULL) { return; @@ -1392,20 +1392,15 @@ btr_free_if_exists( btr_free_root_invalidate(root, mtr); } -/** Free an index tree in a temporary tablespace or during TRUNCATE TABLE. -@param[in] page_id root page id -@param[in] page_size page size */ -void -btr_free( - const page_id_t page_id, - const page_size_t& page_size) +/** Free an index tree in a temporary tablespace. +@param[in] page_id root page id */ +void btr_free(const page_id_t page_id) { mtr_t mtr; mtr.start(); mtr.set_log_mode(MTR_LOG_NO_REDO); - buf_block_t* block = buf_page_get( - page_id, page_size, RW_X_LATCH, &mtr); + buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr); if (block) { ut_ad(page_is_root(block->frame)); @@ -1431,7 +1426,7 @@ btr_read_autoinc(dict_index_t* index) ib_uint64_t autoinc; if (buf_block_t* block = buf_page_get( page_id_t(index->table->space_id, index->page), - page_size_t(index->table->space->flags), + index->table->space->zip_size(), RW_S_LATCH, &mtr)) { autoinc = page_get_autoinc(block->frame); } else { @@ -1463,7 +1458,7 @@ btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no) mtr.start(); buf_block_t* block = buf_page_get( page_id_t(index->table->space_id, index->page), - page_size_t(index->table->space->flags), + index->table->space->zip_size(), RW_S_LATCH, &mtr); ib_uint64_t autoinc = block ? page_get_autoinc(block->frame) : 0; @@ -1508,7 +1503,7 @@ btr_write_autoinc(dict_index_t* index, ib_uint64_t autoinc, bool reset) fil_space_t* space = index->table->space; mtr.set_named_space(space); page_set_autoinc(buf_page_get(page_id_t(space->id, index->page), - page_size_t(space->flags), + space->zip_size(), RW_SX_LATCH, &mtr), index, autoinc, &mtr, reset); mtr.commit(); @@ -2683,12 +2678,12 @@ btr_attach_half_pages( /* for consistency, both blocks should be locked, before change */ if (prev_page_no != FIL_NULL && direction == FSP_DOWN) { prev_block = btr_block_get( - page_id_t(space, prev_page_no), block->page.size, + page_id_t(space, prev_page_no), block->zip_size(), RW_X_LATCH, index, mtr); } if (next_page_no != FIL_NULL && direction != FSP_DOWN) { next_block = btr_block_get( - page_id_t(space, next_page_no), block->page.size, + page_id_t(space, next_page_no), block->zip_size(), RW_X_LATCH, index, mtr); } @@ -2838,7 +2833,7 @@ btr_insert_into_right_sibling( const ulint space = block->page.id.space(); next_block = btr_block_get( - page_id_t(space, next_page_no), block->page.size, + page_id_t(space, next_page_no), block->zip_size(), RW_X_LATCH, cursor->index, mtr); next_page = buf_block_get_frame(next_block); @@ -2864,7 +2859,7 @@ btr_insert_into_right_sibling( if (rec == NULL) { if (is_leaf - && next_block->page.size.is_compressed() + && next_block->page.zip.ssize && !dict_index_is_clust(cursor->index) && !cursor->index->table->is_temporary()) { /* Reset the IBUF_BITMAP_FREE bits, because @@ -2912,7 +2907,7 @@ btr_insert_into_right_sibling( /* Update the free bits of the B-tree page in the insert buffer bitmap. */ - if (next_block->page.size.is_compressed()) { + if (next_block->page.zip.ssize) { ibuf_update_free_bits_zip(next_block, mtr); } else { ibuf_update_free_bits_if_full( @@ -3357,16 +3352,16 @@ func_exit: return(rec); } -/** Removes a page from the level list of pages. +/** Remove a page from the level list of pages. @param[in] space space where removed -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] page page to remove @param[in] index index tree @param[in,out] mtr mini-transaction */ void btr_level_list_remove_func( ulint space, - const page_size_t& page_size, + ulint zip_size, page_t* page, dict_index_t* index, mtr_t* mtr) @@ -3385,7 +3380,7 @@ btr_level_list_remove_func( if (prev_page_no != FIL_NULL) { buf_block_t* prev_block = btr_block_get(page_id_t(space, prev_page_no), - page_size, RW_X_LATCH, index, mtr); + zip_size, RW_X_LATCH, index, mtr); page_t* prev_page = buf_block_get_frame(prev_block); @@ -3403,7 +3398,7 @@ btr_level_list_remove_func( if (next_page_no != FIL_NULL) { buf_block_t* next_block = btr_block_get( - page_id_t(space, next_page_no), page_size, + page_id_t(space, next_page_no), zip_size, RW_X_LATCH, index, mtr); page_t* next_page @@ -3774,7 +3769,7 @@ btr_compress( ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)); - const page_size_t page_size(index->table->space->flags); + const ulint zip_size = index->table->space->zip_size(); MONITOR_INC(MONITOR_INDEX_MERGE_ATTEMPTS); @@ -3932,7 +3927,7 @@ retry: /* Remove the page from the level list */ btr_level_list_remove(index->table->space_id, - page_size, page, index, mtr); + zip_size, page, index, mtr); if (dict_index_is_spatial(index)) { rec_t* my_rec = father_cursor.page_cur.rec; @@ -4062,7 +4057,7 @@ retry: /* Remove the page from the level list */ btr_level_list_remove(index->table->space_id, - page_size, page, index, mtr); + zip_size, page, index, mtr); ut_ad(btr_node_ptr_get_child_page_no( btr_cur_get_rec(&father_cursor), offsets) @@ -4170,7 +4165,7 @@ retry: committed mini-transaction, because in crash recovery, the free bits could momentarily be set too high. */ - if (page_size.is_compressed()) { + if (zip_size) { /* Because the free bits may be incremented and we cannot update the insert buffer bitmap in the same mini-transaction, the only safe @@ -4230,7 +4225,7 @@ func_exit: err_exit: /* We play it safe and reset the free bits. */ - if (page_size.is_compressed() + if (zip_size && merge_page && page_is_leaf(merge_page) && !dict_index_is_clust(index)) { @@ -4405,12 +4400,12 @@ btr_discard_page( left_page_no = btr_page_get_prev(buf_block_get_frame(block), mtr); right_page_no = btr_page_get_next(buf_block_get_frame(block), mtr); - const page_size_t page_size(index->table->space->flags); + const ulint zip_size = index->table->space->zip_size(); if (left_page_no != FIL_NULL) { merge_block = btr_block_get( page_id_t(index->table->space_id, left_page_no), - page_size, RW_X_LATCH, index, mtr); + zip_size, RW_X_LATCH, index, mtr); merge_page = buf_block_get_frame(merge_block); #ifdef UNIV_BTR_DEBUG @@ -4426,7 +4421,7 @@ btr_discard_page( } else if (right_page_no != FIL_NULL) { merge_block = btr_block_get( page_id_t(index->table->space_id, right_page_no), - page_size, RW_X_LATCH, index, mtr); + zip_size, RW_X_LATCH, index, mtr); merge_page = buf_block_get_frame(merge_block); #ifdef UNIV_BTR_DEBUG @@ -4474,7 +4469,7 @@ btr_discard_page( } /* Remove the page from the level list */ - btr_level_list_remove(index->table->space_id, page_size, + btr_level_list_remove(index->table->space_id, zip_size, page, index, mtr); #ifdef UNIV_ZIP_DEBUG @@ -5038,19 +5033,7 @@ btr_validate_level( #endif fil_space_t* space = index->table->space; - const page_size_t table_page_size( - dict_table_page_size(index->table)); - const page_size_t space_page_size(space->flags); - - if (!table_page_size.equals_to(space_page_size)) { - - ib::warn() << "Flags mismatch: table=" << index->table->flags - << ", tablespace=" << space->flags; - - mtr_commit(&mtr); - - return(false); - } + const ulint zip_size = space->zip_size(); while (level != btr_page_get_level(page)) { const rec_t* node_ptr; @@ -5103,7 +5086,7 @@ btr_validate_level( block = btr_block_get( page_id_t(index->table->space_id, left_page_no), - table_page_size, + zip_size, RW_SX_LATCH, index, &mtr); page = buf_block_get_frame(block); left_page_no = btr_page_get_prev(page, &mtr); @@ -5174,7 +5157,7 @@ loop: right_block = btr_block_get( page_id_t(index->table->space_id, right_page_no), - table_page_size, + zip_size, RW_SX_LATCH, index, &mtr); right_page = buf_block_get_frame(right_block); @@ -5352,13 +5335,13 @@ loop: btr_block_get( page_id_t(index->table->space_id, parent_right_page_no), - table_page_size, + zip_size, RW_SX_LATCH, index, &mtr); right_block = btr_block_get( page_id_t(index->table->space_id, right_page_no), - table_page_size, + zip_size, RW_SX_LATCH, index, &mtr); } @@ -5436,21 +5419,21 @@ node_ptr_fails: page_id_t( index->table->space_id, parent_right_page_no), - table_page_size, + zip_size, RW_SX_LATCH, index, &mtr); } } else if (parent_page_no != FIL_NULL) { btr_block_get( page_id_t(index->table->space_id, parent_page_no), - table_page_size, + zip_size, RW_SX_LATCH, index, &mtr); } } block = btr_block_get( page_id_t(index->table->space_id, right_page_no), - table_page_size, + zip_size, RW_SX_LATCH, index, &mtr); page = buf_block_get_frame(block); @@ -5556,9 +5539,9 @@ btr_can_merge_with_page( page = btr_cur_get_page(cursor); const page_id_t page_id(index->table->space_id, page_no); - const page_size_t page_size(index->table->space->flags); + const ulint zip_size = index->table->space->zip_size(); - mblock = btr_block_get(page_id, page_size, RW_X_LATCH, index, mtr); + mblock = btr_block_get(page_id, zip_size, RW_X_LATCH, index, mtr); mpage = buf_block_get_frame(mblock); n_recs = page_get_n_recs(page); @@ -5574,7 +5557,7 @@ btr_can_merge_with_page( /* If compression padding tells us that merging will result in too packed up page i.e.: which is likely to cause compression failure then don't merge the pages. */ - if (page_size.is_compressed() && page_is_leaf(mpage) + if (zip_size && page_is_leaf(mpage) && (page_get_data_size(mpage) + data_size >= dict_index_zip_pad_optimal_page_size(index))) { diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 09f31259e8e..9cad745aa0d 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -121,7 +121,7 @@ PageBulk::init() } else { new_block = btr_block_get( page_id_t(m_index->table->space_id, m_page_no), - page_size_t(m_index->table->space->flags), + m_index->table->space->zip_size(), RW_X_LATCH, m_index, &m_mtr); new_page = buf_block_get_frame(new_block); @@ -589,8 +589,9 @@ PageBulk::needExt( const dtuple_t* tuple, ulint rec_size) { - return(page_zip_rec_needs_ext(rec_size, m_is_comp, - dtuple_get_n_fields(tuple), m_block->page.size)); + return page_zip_rec_needs_ext(rec_size, m_is_comp, + dtuple_get_n_fields(tuple), + m_block->zip_size()); } /** Store external record @@ -664,7 +665,7 @@ PageBulk::latch() __FILE__, __LINE__, &m_mtr)) { m_block = buf_page_get_gen( page_id_t(m_index->table->space_id, m_page_no), - page_size_t(m_index->table->space->flags), + m_index->table->space->zip_size(), RW_X_LATCH, m_block, BUF_GET_IF_IN_POOL, __FILE__, __LINE__, &m_mtr, &m_err); @@ -1017,7 +1018,7 @@ BtrBulk::finish(dberr_t err) ut_ad(last_page_no != FIL_NULL); last_block = btr_block_get( page_id_t(m_index->table->space_id, last_page_no), - page_size_t(m_index->table->space->flags), + m_index->table->space->zip_size(), RW_X_LATCH, m_index, &mtr); first_rec = page_rec_get_next( page_get_infimum_rec(last_block->frame)); diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index f4cbb4e51a3..59704201c4e 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -210,6 +210,7 @@ btr_rec_free_externally_stored_fields( /** Latches the leaf page or pages requested. @param[in] block leaf page where the search converged @param[in] page_id page id of the leaf +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] latch_mode BTR_SEARCH_LEAF, ... @param[in] cursor cursor @param[in] mtr mini-transaction @@ -218,7 +219,7 @@ btr_latch_leaves_t btr_cur_latch_leaves( buf_block_t* block, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint latch_mode, btr_cur_t* cursor, mtr_t* mtr) @@ -249,7 +250,7 @@ btr_cur_latch_leaves( mode = latch_mode == BTR_MODIFY_LEAF ? RW_X_LATCH : RW_S_LATCH; latch_leaves.savepoints[1] = mtr_set_savepoint(mtr); - get_block = btr_block_get(page_id, page_size, mode, + get_block = btr_block_get(page_id, zip_size, mode, cursor->index, mtr); latch_leaves.blocks[1] = get_block; #ifdef UNIV_BTR_DEBUG @@ -282,7 +283,7 @@ btr_cur_latch_leaves( latch_leaves.savepoints[0] = mtr_set_savepoint(mtr); get_block = btr_block_get( page_id_t(page_id.space(), left_page_no), - page_size, RW_X_LATCH, cursor->index, mtr); + zip_size, RW_X_LATCH, cursor->index, mtr); latch_leaves.blocks[0] = get_block; if (spatial) { @@ -298,7 +299,7 @@ btr_cur_latch_leaves( latch_leaves.savepoints[1] = mtr_set_savepoint(mtr); get_block = btr_block_get( - page_id, page_size, RW_X_LATCH, cursor->index, mtr); + page_id, zip_size, RW_X_LATCH, cursor->index, mtr); latch_leaves.blocks[1] = get_block; #ifdef UNIV_BTR_DEBUG @@ -329,7 +330,7 @@ btr_cur_latch_leaves( latch_leaves.savepoints[2] = mtr_set_savepoint(mtr); get_block = btr_block_get( page_id_t(page_id.space(), right_page_no), - page_size, RW_X_LATCH, cursor->index, mtr); + zip_size, RW_X_LATCH, cursor->index, mtr); latch_leaves.blocks[2] = get_block; #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(get_block->frame) @@ -357,7 +358,7 @@ btr_cur_latch_leaves( latch_leaves.savepoints[0] = mtr_set_savepoint(mtr); get_block = btr_block_get( page_id_t(page_id.space(), left_page_no), - page_size, mode, cursor->index, mtr); + zip_size, mode, cursor->index, mtr); latch_leaves.blocks[0] = get_block; cursor->left_block = get_block; #ifdef UNIV_BTR_DEBUG @@ -369,7 +370,7 @@ btr_cur_latch_leaves( } latch_leaves.savepoints[1] = mtr_set_savepoint(mtr); - get_block = btr_block_get(page_id, page_size, mode, + get_block = btr_block_get(page_id, zip_size, mode, cursor->index, mtr); latch_leaves.blocks[1] = get_block; #ifdef UNIV_BTR_DEBUG @@ -509,7 +510,7 @@ incompatible: buf_block_t* block = buf_page_get( page_id_t(space->id, mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)), - univ_page_size, RW_S_LATCH, mtr); + 0, RW_S_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE); if (fil_page_get_type(block->frame) != FIL_PAGE_TYPE_BLOB || mach_read_from_4(&block->frame[FIL_PAGE_DATA @@ -591,7 +592,7 @@ inconsistent: } else { col->def_val.data = btr_copy_externally_stored_field( &col->def_val.len, data, - cur.page_cur.block->page.size, + cur.page_cur.block->zip_size(), len, index->table->heap); } } @@ -756,8 +757,7 @@ btr_cur_optimistic_latch_leaves( cursor->left_block = btr_block_get( page_id_t(cursor->index->table->space_id, left_page_no), - page_size_t(cursor->index->table->space - ->flags), + cursor->index->table->space->zip_size(), mode, cursor->index, mtr); } else { cursor->left_block = NULL; @@ -865,7 +865,7 @@ btr_cur_latch_for_root_leaf( @param[in] lock_intention lock intention for the tree operation @param[in] rec record (current node_ptr) @param[in] rec_size size of the record or max size of node_ptr -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] mtr mtr @return true if tree modification is needed */ static @@ -876,7 +876,7 @@ btr_cur_will_modify_tree( btr_intention_t lock_intention, const rec_t* rec, ulint rec_size, - const page_size_t& page_size, + ulint zip_size, mtr_t* mtr) { ut_ad(!page_is_leaf(page)); @@ -964,9 +964,8 @@ btr_cur_will_modify_tree( This is based on the worst case, and we could invoke page_zip_available() on the block->page.zip. */ /* needs 2 records' space also for worst compress rate. */ - if (page_size.is_compressed() - && page_zip_empty_size(index->n_fields, - page_size.physical()) + if (zip_size + && page_zip_empty_size(index->n_fields, zip_size) <= rec_size * 2 + page_get_data_size(page) + page_dir_calc_reserved_space(n_recs + 2)) { return(true); @@ -1462,7 +1461,7 @@ btr_cur_search_to_nth_level_func( page_cursor = btr_cur_get_page_cur(cursor); - const page_size_t page_size(index->table->space->flags); + const ulint zip_size = index->table->space->zip_size(); /* Start with the root page. */ page_id_t page_id(index->table->space_id, index->page); @@ -1545,7 +1544,7 @@ search_loop: retry_page_get: ut_ad(n_blocks < BTR_MAX_LEVELS); tree_savepoints[n_blocks] = mtr_set_savepoint(mtr); - block = buf_page_get_gen(page_id, page_size, rw_latch, guess, + block = buf_page_get_gen(page_id, zip_size, rw_latch, guess, buf_mode, file, line, mtr, &err); tree_blocks[n_blocks] = block; @@ -1581,7 +1580,7 @@ retry_page_get: ut_ad(!dict_index_is_spatial(index)); if (ibuf_insert(IBUF_OP_INSERT, tuple, index, - page_id, page_size, cursor->thr)) { + page_id, zip_size, cursor->thr)) { cursor->flag = BTR_CUR_INSERT_TO_IBUF; @@ -1594,7 +1593,7 @@ retry_page_get: ut_ad(!dict_index_is_spatial(index)); if (ibuf_insert(IBUF_OP_DELETE_MARK, tuple, - index, page_id, page_size, + index, page_id, zip_size, cursor->thr)) { cursor->flag = BTR_CUR_DEL_MARK_IBUF; @@ -1614,7 +1613,7 @@ retry_page_get: /* The record cannot be purged yet. */ cursor->flag = BTR_CUR_DELETE_REF; } else if (ibuf_insert(IBUF_OP_DELETE, tuple, - index, page_id, page_size, + index, page_id, zip_size, cursor->thr)) { /* The purge was buffered. */ @@ -1661,7 +1660,7 @@ retry_page_get: = mtr_set_savepoint(mtr); get_block = buf_page_get_gen( page_id_t(page_id.space(), left_page_no), - page_size, rw_latch, NULL, buf_mode, + zip_size, rw_latch, NULL, buf_mode, file, line, mtr, &err); prev_tree_blocks[prev_n_blocks] = get_block; prev_n_blocks++; @@ -1691,7 +1690,7 @@ retry_page_get: tree_blocks[n_blocks]); tree_savepoints[n_blocks] = mtr_set_savepoint(mtr); - block = buf_page_get_gen(page_id, page_size, rw_latch, NULL, + block = buf_page_get_gen(page_id, zip_size, rw_latch, NULL, buf_mode, file, line, mtr, &err); tree_blocks[n_blocks] = block; @@ -1789,7 +1788,7 @@ retry_page_get: if (rw_latch == RW_NO_LATCH) { latch_leaves = btr_cur_latch_leaves( - block, page_id, page_size, latch_mode, + block, page_id, zip_size, latch_mode, cursor, mtr); } @@ -2153,7 +2152,7 @@ need_opposite_intention: && latch_mode == BTR_MODIFY_TREE && !btr_cur_will_modify_tree( index, page, lock_intention, node_ptr, - node_ptr_max_size, page_size, mtr) + node_ptr_max_size, zip_size, mtr) && !rtree_parent_modified) { ut_ad(upper_rw_latch == RW_X_LATCH); ut_ad(n_releases <= n_blocks); @@ -2351,12 +2350,12 @@ need_opposite_intention: if (latch_mode == BTR_CONT_MODIFY_TREE) { child_block = btr_block_get( - page_id, page_size, RW_X_LATCH, + page_id, zip_size, RW_X_LATCH, index, mtr); } else { ut_ad(latch_mode == BTR_CONT_SEARCH_TREE); child_block = btr_block_get( - page_id, page_size, RW_SX_LATCH, + page_id, zip_size, RW_SX_LATCH, index, mtr); } @@ -2574,7 +2573,7 @@ btr_cur_open_at_index_side_func( cursor->index = index; page_id_t page_id(index->table->space_id, index->page); - const page_size_t page_size(index->table->space->flags); + const ulint zip_size = index->table->space->zip_size(); if (root_leaf_rw_latch == RW_X_LATCH) { node_ptr_max_size = btr_node_ptr_max_size(index); @@ -2597,7 +2596,7 @@ btr_cur_open_at_index_side_func( } tree_savepoints[n_blocks] = mtr_set_savepoint(mtr); - block = buf_page_get_gen(page_id, page_size, rw_latch, NULL, + block = buf_page_get_gen(page_id, zip_size, rw_latch, NULL, BUF_GET, file, line, mtr, &err); ut_ad((block != NULL) == (err == DB_SUCCESS)); tree_blocks[n_blocks] = block; @@ -2653,12 +2652,12 @@ btr_cur_open_at_index_side_func( if (height == level) { if (srv_read_only_mode) { btr_cur_latch_leaves( - block, page_id, page_size, + block, page_id, zip_size, latch_mode, cursor, mtr); } else if (height == 0) { if (rw_latch == RW_NO_LATCH) { btr_cur_latch_leaves( - block, page_id, page_size, + block, page_id, zip_size, latch_mode, cursor, mtr); } /* In versions <= 3.23.52 we had @@ -2789,7 +2788,7 @@ btr_cur_open_at_index_side_func( if (latch_mode == BTR_MODIFY_TREE && !btr_cur_will_modify_tree( cursor->index, page, lock_intention, node_ptr, - node_ptr_max_size, page_size, mtr)) { + node_ptr_max_size, zip_size, mtr)) { ut_ad(upper_rw_latch == RW_X_LATCH); ut_ad(n_releases <= n_blocks); @@ -2931,7 +2930,7 @@ btr_cur_open_at_rnd_pos_func( cursor->index = index; page_id_t page_id(index->table->space_id, index->page); - const page_size_t page_size(index->table->space->flags); + const ulint zip_size = index->table->space->zip_size(); dberr_t err = DB_SUCCESS; if (root_leaf_rw_latch == RW_X_LATCH) { @@ -2955,7 +2954,7 @@ btr_cur_open_at_rnd_pos_func( } tree_savepoints[n_blocks] = mtr_set_savepoint(mtr); - block = buf_page_get_gen(page_id, page_size, rw_latch, NULL, + block = buf_page_get_gen(page_id, zip_size, rw_latch, NULL, BUF_GET, file, line, mtr, &err); tree_blocks[n_blocks] = block; @@ -3008,7 +3007,7 @@ btr_cur_open_at_rnd_pos_func( if (rw_latch == RW_NO_LATCH || srv_read_only_mode) { btr_cur_latch_leaves( - block, page_id, page_size, + block, page_id, zip_size, latch_mode, cursor, mtr); } @@ -3084,7 +3083,7 @@ btr_cur_open_at_rnd_pos_func( if (latch_mode == BTR_MODIFY_TREE && !btr_cur_will_modify_tree( cursor->index, page, lock_intention, node_ptr, - node_ptr_max_size, page_size, mtr)) { + node_ptr_max_size, zip_size, mtr)) { ut_ad(upper_rw_latch == RW_X_LATCH); ut_ad(n_releases <= n_blocks); @@ -3297,12 +3296,12 @@ btr_cur_prefetch_siblings( if (left_page_no != FIL_NULL) { buf_read_page_background( page_id_t(block->page.id.space(), left_page_no), - block->page.size, false); + block->zip_size(), false); } if (right_page_no != FIL_NULL) { buf_read_page_background( page_id_t(block->page.id.space(), right_page_no), - block->page.size, false); + block->zip_size(), false); } if (left_page_no != FIL_NULL || right_page_no != FIL_NULL) { @@ -3369,12 +3368,11 @@ btr_cur_optimistic_insert( || (flags & BTR_CREATE_FLAG)); ut_ad(dtuple_check_typed(entry)); - const page_size_t& page_size = block->page.size; - #ifdef UNIV_DEBUG_VALGRIND - if (page_size.is_compressed()) { - UNIV_MEM_ASSERT_RW(page, page_size.logical()); - UNIV_MEM_ASSERT_RW(block->page.zip.data, page_size.physical()); + if (block->page.zip.data) { + UNIV_MEM_ASSERT_RW(page, srv_page_size); + UNIV_MEM_ASSERT_RW(block->page.zip.data, + block->zip_size()); } #endif /* UNIV_DEBUG_VALGRIND */ @@ -3389,7 +3387,8 @@ btr_cur_optimistic_insert( rec_size = rec_get_converted_size(index, entry, n_ext); if (page_zip_rec_needs_ext(rec_size, page_is_comp(page), - dtuple_get_n_fields(entry), page_size)) { + dtuple_get_n_fields(entry), + block->zip_size())) { convert_big_rec: /* The record is so big that we have to store some fields externally on separate database pages */ @@ -3403,7 +3402,7 @@ convert_big_rec: rec_size = rec_get_converted_size(index, entry, n_ext); } - if (page_size.is_compressed() && page_zip_is_too_big(index, entry)) { + if (block->page.zip.data && page_zip_is_too_big(index, entry)) { if (big_rec_vec != NULL) { dtuple_convert_back_big_rec(index, entry, big_rec_vec); } @@ -3414,7 +3413,7 @@ convert_big_rec: LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page), goto fail); - if (leaf && page_size.is_compressed() + if (block->page.zip.data && leaf && (page_get_data_size(page) + rec_size >= dict_index_zip_pad_optimal_page_size(index))) { /* If compression padding tells us that insertion will @@ -3457,7 +3456,7 @@ fail_err: we have to split the page to reserve enough free space for future updates of records. */ - if (leaf && !page_size.is_compressed() && dict_index_is_clust(index) + if (leaf && !block->page.zip.data && dict_index_is_clust(index) && page_get_n_recs(page) >= 2 && dict_index_get_space_reserve() + rec_size > max_size && (btr_page_get_split_rec_to_right(cursor, &dummy) @@ -3520,7 +3519,7 @@ fail_err: } if (*rec) { - } else if (page_size.is_compressed()) { + } else if (block->page.zip.data) { ut_ad(!index->table->is_temporary()); /* Reset the IBUF_BITMAP_FREE bits, because page_cur_tuple_insert() will have attempted page @@ -3596,7 +3595,7 @@ fail_err: committed mini-transaction, because in crash recovery, the free bits could momentarily be set too high. */ - if (page_size.is_compressed()) { + if (block->page.zip.data) { /* Update the bits in the same mini-transaction. */ ibuf_update_free_bits_zip(block, mtr); } else { @@ -3696,7 +3695,7 @@ btr_cur_pessimistic_insert( if (page_zip_rec_needs_ext(rec_get_converted_size(index, entry, n_ext), index->table->not_redundant(), dtuple_get_n_fields(entry), - btr_cur_get_block(cursor)->page.size) + btr_cur_get_block(cursor)->zip_size()) || UNIV_UNLIKELY(entry->is_alter_metadata() && !dfield_is_ext( dtuple_get_nth_field( @@ -4337,7 +4336,7 @@ static void btr_cur_trim_alter_metadata(dtuple_t* entry, buf_block_t* block = buf_page_get( page_id_t(index->table->space->id, mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)), - univ_page_size, RW_S_LATCH, &mtr); + 0, RW_S_LATCH, &mtr); buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE); ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_TYPE_BLOB); ut_ad(mach_read_from_4(&block->frame[FIL_PAGE_DATA @@ -4570,7 +4569,7 @@ any_extern: if (page_zip_rec_needs_ext(new_rec_size, page_is_comp(page), dict_index_get_n_fields(index), - block->page.size)) { + block->zip_size())) { goto any_extern; } @@ -4749,7 +4748,8 @@ btr_cur_pess_upd_restore_supremum( const page_id_t page_id(block->page.id.space(), prev_page_no); ut_ad(prev_page_no != FIL_NULL); - prev_block = buf_page_get_with_no_latch(page_id, block->page.size, mtr); + prev_block = buf_page_get_with_no_latch(page_id, block->zip_size(), + mtr); #ifdef UNIV_BTR_DEBUG ut_a(btr_page_get_next(prev_block->frame, mtr) == page_get_page_no(page)); @@ -4938,7 +4938,7 @@ btr_cur_pessimistic_update( rec_get_converted_size(index, new_entry, n_ext), page_is_comp(page), dict_index_get_n_fields(index), - block->page.size) + block->zip_size()) || (UNIV_UNLIKELY(update->is_alter_metadata()) && !dfield_is_ext(dtuple_get_nth_field( new_entry, @@ -6062,7 +6062,7 @@ discard_page: || btr_cur_will_modify_tree( index, page, BTR_INTENTION_DELETE, rec, btr_node_ptr_max_size(index), - block->page.size, mtr); + block->zip_size(), mtr); page_cur_delete_rec(btr_cur_get_page_cur(cursor), index, offsets, mtr); #ifdef UNIV_ZIP_DEBUG @@ -6212,7 +6212,7 @@ btr_estimate_n_rows_in_range_on_level( const fil_space_t* space = index->table->space; page_id_t page_id(space->id, slot1->page_no); - const page_size_t page_size(space->flags); + const ulint zip_size = space->zip_size(); level = slot1->page_level; @@ -6229,7 +6229,7 @@ btr_estimate_n_rows_in_range_on_level( attempting to read a page that is no longer part of the B-tree. We pass BUF_GET_POSSIBLY_FREED in order to silence a debug assertion about this. */ - block = buf_page_get_gen(page_id, page_size, RW_S_LATCH, + block = buf_page_get_gen(page_id, zip_size, RW_S_LATCH, NULL, BUF_GET_POSSIBLY_FREED, __FILE__, __LINE__, &mtr, &err); @@ -7450,7 +7450,7 @@ struct btr_blob_log_check_t { mtr_x_lock(dict_index_get_lock(index), m_mtr); m_pcur->btr_cur.page_cur.block = btr_block_get( page_id_t(index->table->space_id, page_no), - page_size_t(index->table->space->flags), + index->table->space->zip_size(), RW_X_LATCH, index, m_mtr); m_pcur->btr_cur.page_cur.rec = m_pcur->btr_cur.page_cur.block->frame @@ -7538,9 +7538,6 @@ btr_store_big_rec_extern_fields( ut_ad(buf_block_get_frame(rec_block) == page_align(rec)); ut_a(dict_index_is_clust(index)); - ut_ad(dict_table_page_size(index->table) - .equals_to(rec_block->page.size)); - btr_blob_log_check_t redo_log(pcur, btr_mtr, offsets, &rec_block, &rec, op); page_zip = buf_block_get_page_zip(rec_block); @@ -7585,7 +7582,7 @@ btr_store_big_rec_extern_fields( #endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */ /* Space available in compressed page to carry blob data */ - const ulint payload_size_zip = rec_block->page.size.physical() + const ulint payload_size_zip = rec_block->physical_size() - FIL_PAGE_DATA; /* Space available in uncompressed page to carry blob data */ @@ -7646,7 +7643,7 @@ btr_store_big_rec_extern_fields( mtr.set_flush_observer(btr_mtr->get_flush_observer()); buf_page_get(rec_block->page.id, - rec_block->page.size, RW_X_LATCH, &mtr); + rec_block->zip_size(), RW_X_LATCH, &mtr); if (prev_page_no == FIL_NULL) { hint_page_no = 1 + rec_page_no; @@ -7694,7 +7691,7 @@ btr_store_big_rec_extern_fields( prev_block = buf_page_get( page_id_t(space_id, prev_page_no), - rec_block->page.size, + rec_block->zip_size(), RW_X_LATCH, &mtr); buf_block_dbg_add_level(prev_block, @@ -8057,10 +8054,9 @@ btr_free_externally_stored_field( ut_ad(space_id == index->table->space->id); ut_ad(space_id == index->table->space_id); - const page_size_t ext_page_size(dict_table_page_size(index->table)); - const page_size_t& rec_page_size(rec == NULL - ? univ_page_size - : ext_page_size); + const ulint ext_zip_size = index->table->space->zip_size(); + const ulint rec_zip_size = rec ? ext_zip_size : 0; + if (rec == NULL) { /* This is a call from row_purge_upd_exist_or_extern(). */ ut_ad(!page_zip); @@ -8087,7 +8083,7 @@ btr_free_externally_stored_field( #ifdef UNIV_DEBUG rec_block = #endif /* UNIV_DEBUG */ - buf_page_get(page_id, rec_page_size, RW_X_LATCH, &mtr); + buf_page_get(page_id, rec_zip_size, RW_X_LATCH, &mtr); buf_block_dbg_add_level(rec_block, SYNC_NO_ORDER_CHECK); page_no = mach_read_from_4(field_ref + BTR_EXTERN_PAGE_NO); @@ -8113,13 +8109,13 @@ btr_free_externally_stored_field( } ext_block = buf_page_get( - page_id_t(space_id, page_no), ext_page_size, + page_id_t(space_id, page_no), ext_zip_size, RW_X_LATCH, &mtr); buf_block_dbg_add_level(ext_block, SYNC_EXTERN_STORAGE); page = buf_block_get_frame(ext_block); - if (ext_page_size.is_compressed()) { + if (ext_zip_size) { /* Note that page_zip will be NULL in row_purge_upd_exist_or_extern(). */ switch (fil_page_get_type(page)) { @@ -8294,7 +8290,7 @@ btr_copy_blob_prefix( mtr_start(&mtr); block = buf_page_get(page_id_t(space_id, page_no), - univ_page_size, RW_S_LATCH, &mtr); + 0, RW_S_LATCH, &mtr); buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE); page = buf_block_get_frame(block); @@ -8332,7 +8328,7 @@ by a lock or a page latch. @param[out] buf the externally stored part of the field, or a prefix of it @param[in] len length of buf, in bytes -@param[in] page_size compressed BLOB page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size @param[in] space_id space id of the BLOB pages @param[in] offset offset on the first BLOB page @return number of bytes written to buf */ @@ -8341,7 +8337,7 @@ ulint btr_copy_zblob_prefix( byte* buf, ulint len, - const page_size_t& page_size, + ulint zip_size, ulint space_id, ulint page_no, ulint offset) @@ -8361,7 +8357,8 @@ btr_copy_zblob_prefix( heap = mem_heap_create(40000); page_zip_set_alloc(&d_stream, heap); - ut_ad(page_size.is_compressed()); + ut_ad(zip_size); + ut_ad(ut_is_2pow(zip_size)); ut_ad(space_id); err = inflateInit(&d_stream); @@ -8376,7 +8373,7 @@ btr_copy_zblob_prefix( is being held on the clustered index record, or, in row_merge_copy_blobs(), by an exclusive table lock. */ bpage = buf_page_get_zip(page_id_t(space_id, page_no), - page_size); + zip_size); if (UNIV_UNLIKELY(!bpage)) { ib::error() << "Cannot load compressed BLOB " @@ -8408,8 +8405,7 @@ btr_copy_zblob_prefix( } d_stream.next_in = bpage->zip.data + offset; - d_stream.avail_in = static_cast(page_size.physical() - - offset); + d_stream.avail_in = uInt(zip_size - offset); err = inflate(&d_stream, Z_NO_FLUSH); switch (err) { @@ -8479,7 +8475,7 @@ by a lock or a page latch. @param[out] buf the externally stored part of the field, or a prefix of it @param[in] len length of buf, in bytes -@param[in] page_size BLOB page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] space_id space id of the first BLOB page @param[in] page_no page number of the first BLOB page @param[in] offset offset on the first BLOB page @@ -8489,7 +8485,7 @@ ulint btr_copy_externally_stored_field_prefix_low( byte* buf, ulint len, - const page_size_t& page_size, + ulint zip_size, ulint space_id, ulint page_no, ulint offset) @@ -8498,11 +8494,10 @@ btr_copy_externally_stored_field_prefix_low( return(0); } - if (page_size.is_compressed()) { - return(btr_copy_zblob_prefix(buf, len, page_size, + if (zip_size) { + return(btr_copy_zblob_prefix(buf, len, zip_size, space_id, page_no, offset)); } else { - ut_ad(page_size.equals_to(univ_page_size)); return(btr_copy_blob_prefix(buf, len, space_id, page_no, offset)); } @@ -8512,7 +8507,7 @@ btr_copy_externally_stored_field_prefix_low( The clustered index record must be protected by a lock or a page latch. @param[out] buf the field, or a prefix of it @param[in] len length of buf, in bytes -@param[in] page_size BLOB page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] data 'internally' stored part of the field containing also the reference to the external part; must be protected by a lock or a page latch @@ -8523,7 +8518,7 @@ ulint btr_copy_externally_stored_field_prefix( byte* buf, ulint len, - const page_size_t& page_size, + ulint zip_size, const byte* data, ulint local_len) { @@ -8562,7 +8557,7 @@ btr_copy_externally_stored_field_prefix( return(local_len + btr_copy_externally_stored_field_prefix_low(buf + local_len, len - local_len, - page_size, + zip_size, space_id, page_no, offset)); } @@ -8573,7 +8568,7 @@ The clustered index record must be protected by a lock or a page latch. @param[in] data 'internally' stored part of the field containing also the reference to the external part; must be protected by a lock or a page latch -@param[in] page_size BLOB page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] local_len length of data @param[in,out] heap mem heap @return the whole field copied to heap */ @@ -8581,7 +8576,7 @@ byte* btr_copy_externally_stored_field( ulint* len, const byte* data, - const page_size_t& page_size, + ulint zip_size, ulint local_len, mem_heap_t* heap) { @@ -8612,7 +8607,7 @@ btr_copy_externally_stored_field( *len = local_len + btr_copy_externally_stored_field_prefix_low(buf + local_len, extern_len, - page_size, + zip_size, space_id, page_no, offset); @@ -8623,7 +8618,7 @@ btr_copy_externally_stored_field( @param[in] rec record in a clustered index; must be protected by a lock or a page latch @param[in] offset array returned by rec_get_offsets() -@param[in] page_size BLOB page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] no field number @param[out] len length of the field @param[in,out] heap mem heap @@ -8632,7 +8627,7 @@ byte* btr_rec_copy_externally_stored_field( const rec_t* rec, const ulint* offsets, - const page_size_t& page_size, + ulint zip_size, ulint no, ulint* len, mem_heap_t* heap) @@ -8666,5 +8661,5 @@ btr_rec_copy_externally_stored_field( } return(btr_copy_externally_stored_field(len, data, - page_size, local_len, heap)); + zip_size, local_len, heap)); } diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc index 86daa90dc0b..ffdc448a68e 100644 --- a/storage/innobase/btr/btr0defragment.cc +++ b/storage/innobase/btr/btr0defragment.cc @@ -167,7 +167,7 @@ btr_defragment_add_index( // Load index rood page. buf_block_t* block = btr_block_get( page_id_t(index->table->space_id, index->page), - page_size_t(index->table->space->flags), + index->table->space->zip_size(), RW_NO_LATCH, index, &mtr); page_t* page = NULL; @@ -376,7 +376,7 @@ btr_defragment_merge_pages( dict_index_t* index, /*!< in: index tree */ buf_block_t* from_block, /*!< in: origin of merge */ buf_block_t* to_block, /*!< in: destination of merge */ - const page_size_t page_size, /*!< in: page size of the block */ + ulint zip_size, /*!< in: ROW_FORMAT=COMPRESSED size */ ulint reserved_space, /*!< in: space reserved for future insert to avoid immediate page split */ ulint* max_data_size, /*!< in/out: max data size to @@ -404,7 +404,7 @@ btr_defragment_merge_pages( // Estimate how many records can be moved from the from_page to // the to_page. - if (page_size.is_compressed()) { + if (zip_size) { ulint page_diff = srv_page_size - *max_data_size; max_ins_size_to_use = (max_ins_size_to_use > page_diff) ? max_ins_size_to_use - page_diff : 0; @@ -472,7 +472,7 @@ btr_defragment_merge_pages( // Set ibuf free bits if necessary. if (!dict_index_is_clust(index) && page_is_leaf(to_page)) { - if (page_size.is_compressed()) { + if (zip_size) { ibuf_reset_free_bits(to_block); } else { ibuf_update_free_bits_if_full( @@ -489,7 +489,7 @@ btr_defragment_merge_pages( btr_search_drop_page_hash_index(from_block); btr_level_list_remove( index->table->space_id, - page_size, from_page, index, mtr); + zip_size, from_page, index, mtr); btr_node_ptr_delete(index, from_block, mtr); /* btr_blob_dbg_remove(from_page, index, "btr_defragment_n_pages"); */ @@ -573,7 +573,7 @@ btr_defragment_n_pages( } first_page = buf_block_get_frame(block); - const page_size_t page_size(index->table->space->flags); + const ulint zip_size = index->table->space->zip_size(); /* 1. Load the pages and calculate the total data size. */ blocks[0] = block; @@ -589,7 +589,7 @@ btr_defragment_n_pages( } blocks[i] = btr_block_get(page_id_t(index->table->space_id, - page_no), page_size, + page_no), zip_size, RW_X_LATCH, index, mtr); } @@ -615,7 +615,7 @@ btr_defragment_n_pages( optimal_page_size = page_get_free_space_of_empty( page_is_comp(first_page)); // For compressed pages, we take compression failures into account. - if (page_size.is_compressed()) { + if (zip_size) { ulint size = 0; uint i = 0; // We estimate the optimal data size of the index use samples of @@ -658,7 +658,7 @@ btr_defragment_n_pages( // Start from the second page. for (uint i = 1; i < n_pages; i ++) { buf_block_t* new_block = btr_defragment_merge_pages( - index, blocks[i], current_block, page_size, + index, blocks[i], current_block, zip_size, reserved_space, &max_data_size, heap, mtr); if (new_block != current_block) { n_defragmented ++; diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc index 20cb199fbe5..f0cc6b245d4 100644 --- a/storage/innobase/btr/btr0pcur.cc +++ b/storage/innobase/btr/btr0pcur.cc @@ -476,7 +476,7 @@ btr_pcur_move_to_next_page( next_block = btr_block_get( page_id_t(block->page.id.space(), next_page_no), - block->page.size, mode, + block->zip_size(), mode, btr_pcur_get_btr_cur(cursor)->index, mtr); if (UNIV_UNLIKELY(!next_block)) { diff --git a/storage/innobase/btr/btr0scrub.cc b/storage/innobase/btr/btr0scrub.cc index 7d8966d4109..a4ae24b8946 100644 --- a/storage/innobase/btr/btr0scrub.cc +++ b/storage/innobase/btr/btr0scrub.cc @@ -434,7 +434,7 @@ btr_pessimistic_scrub( const ulint page_no = mach_read_from_4(page + FIL_PAGE_OFFSET); const ulint left_page_no = mach_read_from_4(page + FIL_PAGE_PREV); const ulint right_page_no = mach_read_from_4(page + FIL_PAGE_NEXT); - const page_size_t page_size(index->table->space->flags); + const ulint zip_size = index->table->space->zip_size(); /** * When splitting page, we need X-latches on left/right brothers @@ -449,16 +449,16 @@ btr_pessimistic_scrub( */ mtr->release_block_at_savepoint(scrub_data->savepoint, block); - buf_block_t* get_block __attribute__((unused)) = btr_block_get( + btr_block_get( page_id_t(index->table->space_id, left_page_no), - page_size, RW_X_LATCH, index, mtr); + zip_size, RW_X_LATCH, index, mtr); /** * Refetch block and re-initialize page */ block = btr_block_get( page_id_t(index->table->space_id, page_no), - page_size, RW_X_LATCH, index, mtr); + zip_size, RW_X_LATCH, index, mtr); page = buf_block_get_frame(block); @@ -470,9 +470,9 @@ btr_pessimistic_scrub( } if (right_page_no != FIL_NULL) { - buf_block_t* get_block __attribute__((unused))= btr_block_get( + btr_block_get( page_id_t(index->table->space_id, right_page_no), - page_size, RW_X_LATCH, index, mtr); + zip_size, RW_X_LATCH, index, mtr); } /* arguments to btr_page_split_and_insert */ @@ -842,13 +842,15 @@ btr_scrub_start_space( ulint space, /*!< in: space */ btr_scrub_t* scrub_data) /*!< in/out: scrub data */ { - bool found; scrub_data->space = space; scrub_data->current_table = NULL; scrub_data->current_index = NULL; - const page_size_t page_size = fil_space_get_page_size(space, &found); - - scrub_data->compressed = page_size.is_compressed(); + if (fil_space_t* s = fil_space_acquire_silent(space)) { + scrub_data->compressed = s->zip_size(); + s->release(); + } else { + scrub_data->compressed = 0; + } scrub_data->scrubbing = check_scrub_setting(scrub_data); return scrub_data->scrubbing; } diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 37a839727ec..2d5f6a9bf05 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -1287,7 +1287,7 @@ void btr_search_drop_page_hash_when_freed(const page_id_t page_id) are possibly holding, we cannot s-latch the page, but must (recursively) x-latch it, even though we are only reading. */ - block = buf_page_get_gen(page_id, univ_page_size, RW_X_LATCH, NULL, + block = buf_page_get_gen(page_id, 0, RW_X_LATCH, NULL, BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__, &mtr, &err); diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index b707761354e..e6957e43b22 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -33,7 +33,6 @@ Created 11/5/1995 Heikki Tuuri #include "mtr0types.h" #include "mach0data.h" -#include "page0size.h" #include "buf0buf.h" #include "buf0checksum.h" #include @@ -517,7 +516,8 @@ decompress_with_slot: + dst_frame)) { /* Verify encryption checksum before we even try to decrypt. */ - if (!fil_space_verify_crypt_checksum(dst_frame, bpage->size)) { + if (!fil_space_verify_crypt_checksum( + dst_frame, space->zip_size())) { decrypt_failed: ib::error() << "Encrypted page " << bpage->id << " in file " << space->chain.start->name @@ -889,14 +889,14 @@ buf_page_is_checksum_valid_none( /** Check if a page is corrupt. @param[in] check_lsn whether the LSN should be checked @param[in] read_buf database page -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] space tablespace @return whether the page is corrupted */ bool buf_page_is_corrupted( bool check_lsn, const byte* read_buf, - const page_size_t& page_size, + ulint zip_size, #ifndef UNIV_INNOCHECKSUM const fil_space_t* space) #else @@ -931,9 +931,9 @@ buf_page_is_corrupted( return(false); } - if (!page_size.is_compressed() + if (!zip_size && memcmp(read_buf + FIL_PAGE_LSN + 4, - read_buf + page_size.logical() + read_buf + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) { /* Stored log sequence numbers at the start and the end @@ -980,16 +980,15 @@ buf_page_is_corrupted( return(false); } - if (page_size.is_compressed()) { - return(!page_zip_verify_checksum(read_buf, - page_size.physical())); + if (zip_size) { + return !page_zip_verify_checksum(read_buf, zip_size); } checksum_field1 = mach_read_from_4( read_buf + FIL_PAGE_SPACE_OR_CHKSUM); checksum_field2 = mach_read_from_4( - read_buf + page_size.logical() - FIL_PAGE_END_LSN_OLD_CHKSUM); + read_buf + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM); compile_time_assert(!(FIL_PAGE_LSN % 8)); @@ -1000,7 +999,7 @@ buf_page_is_corrupted( read_buf + FIL_PAGE_LSN) == 0) { /* make sure that the page is really empty */ - for (ulint i = 0; i < page_size.logical(); i++) { + for (ulint i = 0; i < srv_page_size; i++) { if (read_buf[i] != 0) { return(true); } @@ -1198,20 +1197,19 @@ buf_madvise_do_dump() /** Dump a page to stderr. @param[in] read_buf database page -@param[in] page_size page size */ -UNIV_INTERN -void -buf_page_print(const byte* read_buf, const page_size_t& page_size) +@param[in] zip_size compressed page size, or 0 */ +void buf_page_print(const byte* read_buf, ulint zip_size) { + const ulint size = zip_size ? zip_size : srv_page_size; dict_index_t* index; ib::info() << "Page dump in ascii and hex (" - << page_size.physical() << " bytes):"; + << size << " bytes):"; - ut_print_buf(stderr, read_buf, page_size.physical()); + ut_print_buf(stderr, read_buf, size); fputs("\nInnoDB: End of page dump\n", stderr); - if (page_size.is_compressed()) { + if (zip_size) { /* Print compressed page. */ ib::info() << "Compressed page type (" << fil_page_get_type(read_buf) @@ -1223,21 +1221,21 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) SRV_CHECKSUM_ALGORITHM_CRC32) << " " << page_zip_calc_checksum( - read_buf, page_size.physical(), + read_buf, zip_size, SRV_CHECKSUM_ALGORITHM_CRC32) << ", " << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_INNODB) << " " << page_zip_calc_checksum( - read_buf, page_size.physical(), + read_buf, zip_size, SRV_CHECKSUM_ALGORITHM_INNODB) << ", " << buf_checksum_algorithm_name( SRV_CHECKSUM_ALGORITHM_NONE) << " " << page_zip_calc_checksum( - read_buf, page_size.physical(), + read_buf, zip_size, SRV_CHECKSUM_ALGORITHM_NONE) << "; page LSN " << mach_read_from_8(read_buf + FIL_PAGE_LSN) @@ -1270,7 +1268,7 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) SRV_CHECKSUM_ALGORITHM_NONE) << " " << BUF_NO_CHECKSUM_MAGIC << ", stored checksum in field2 " - << mach_read_from_4(read_buf + page_size.logical() + << mach_read_from_4(read_buf + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM) << ", calculated checksums for field2: " << buf_checksum_algorithm_name( @@ -1289,7 +1287,7 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size) << " " << mach_read_from_4(read_buf + FIL_PAGE_LSN + 4) << ", low 4 bytes of LSN at page end " - << mach_read_from_4(read_buf + page_size.logical() + << mach_read_from_4(read_buf + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM + 4) << ", page number (if stored to page already) " << mach_read_from_4(read_buf + FIL_PAGE_OFFSET) @@ -3718,12 +3716,9 @@ be implemented at a higher level. In other words, all possible accesses to a given page through this function must be protected by the same set of mutexes or latches. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size @return pointer to the block */ -buf_page_t* -buf_page_get_zip( - const page_id_t page_id, - const page_size_t& page_size) +buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size) { buf_page_t* bpage; BPageMutex* block_mutex; @@ -3732,6 +3727,8 @@ buf_page_get_zip( ibool must_read; buf_pool_t* buf_pool = buf_pool_get(page_id); + ut_ad(zip_size); + ut_ad(ut_is_2pow(zip_size)); buf_pool->stat.n_page_gets++; for (;;) { @@ -3749,7 +3746,7 @@ lookup: /* Page not in buf_pool: needs to be read from file */ ut_ad(!hash_lock); - dberr_t err = buf_read_page(page_id, page_size); + dberr_t err = buf_read_page(page_id, zip_size); if (err != DB_SUCCESS) { ib::error() << "Reading compressed page " << page_id @@ -3900,7 +3897,7 @@ buf_zip_decompress( && (!crypt_data->is_default_encryption() || srv_encrypt_tables); - ut_ad(block->page.size.is_compressed()); + ut_ad(block->zip_size()); ut_a(block->page.id.space() != 0); if (UNIV_UNLIKELY(check && !page_zip_verify_checksum(frame, size))) { @@ -3945,7 +3942,7 @@ buf_zip_decompress( case FIL_PAGE_TYPE_ZBLOB: case FIL_PAGE_TYPE_ZBLOB2: /* Copy to uncompressed storage. */ - memcpy(block->frame, frame, block->page.size.physical()); + memcpy(block->frame, frame, block->zip_size()); if (space) { space->release_for_io(); } @@ -4162,6 +4159,7 @@ buf_wait_for_read( /** This is the general function used to get access to a database page. @param[in] page_id page id +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH @param[in] guess guessed block or NULL @param[in] mode BUF_GET, BUF_GET_IF_IN_POOL, @@ -4169,11 +4167,12 @@ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or BUF_GET_IF_IN_POOL_OR_WATCH @param[in] file file name @param[in] line line where called @param[in] mtr mini-transaction +@param[out] err DB_SUCCESS or error code @return pointer to the block or NULL */ buf_block_t* buf_page_get_gen( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint rw_latch, buf_block_t* guess, ulint mode, @@ -4221,16 +4220,15 @@ buf_page_get_gen( case BUF_GET_IF_IN_POOL: case BUF_GET_IF_IN_POOL_OR_WATCH: case BUF_GET_POSSIBLY_FREED: - bool found; - const page_size_t& space_page_size - = fil_space_get_page_size(page_id.space(), &found); - ut_ad(found); - ut_ad(page_size.equals_to(space_page_size)); + fil_space_t* s = fil_space_acquire_for_io(page_id.space()); + ut_ad(s); + ut_ad(s->zip_size() == zip_size); + s->release_for_io(); } #endif /* UNIV_DEBUG */ ut_ad(!mtr || !ibuf_inside(mtr) - || ibuf_page_low(page_id, page_size, FALSE, file, line, NULL)); + || ibuf_page_low(page_id, zip_size, FALSE, file, line, NULL)); buf_pool->stat.n_page_gets++; hash_lock = buf_page_hash_lock_get(buf_pool, page_id); @@ -4339,10 +4337,10 @@ loop: corrupted, or if an encrypted page with a valid checksum cannot be decypted. */ - dberr_t local_err = buf_read_page(page_id, page_size); + dberr_t local_err = buf_read_page(page_id, zip_size); if (local_err == DB_SUCCESS) { - buf_read_ahead_random(page_id, page_size, + buf_read_ahead_random(page_id, zip_size, ibuf_inside(mtr)); retries = 0; @@ -4423,8 +4421,10 @@ loop: rw_lock_s_unlock(hash_lock); got_block: - switch (mode) { + default: + ut_ad(block->zip_size() == zip_size); + break; case BUF_GET_IF_IN_POOL: case BUF_PEEK_IF_IN_POOL: case BUF_EVICT_IF_IN_POOL: @@ -4633,7 +4633,7 @@ evict_from_pool: #endif /* UNIV_IBUF_COUNT_DEBUG */ } else { ibuf_merge_or_delete_for_page( - block, page_id, &page_size, TRUE); + block, block->page.id, zip_size, true); } } @@ -4833,7 +4833,7 @@ evict_from_pool: /* In the case of a first access, try to apply linear read-ahead */ - buf_read_ahead_linear(page_id, page_size, ibuf_inside(mtr)); + buf_read_ahead_linear(page_id, zip_size, ibuf_inside(mtr)); } #ifdef UNIV_IBUF_COUNT_DEBUG @@ -4889,7 +4889,7 @@ buf_page_optimistic_get( buf_page_make_young_if_needed(&block->page); ut_ad(!ibuf_inside(mtr) - || ibuf_page(block->page.id, block->page.size, NULL)); + || ibuf_page(block->page.id, block->physical_size(), NULL)); mtr_memo_type_t fix_type; @@ -4949,7 +4949,7 @@ buf_page_optimistic_get( if (!access_time) { /* In the case of a first access, try to apply linear read-ahead */ - buf_read_ahead_linear(block->page.id, block->page.size, + buf_read_ahead_linear(block->page.id, block->zip_size(), ibuf_inside(mtr)); } @@ -5189,13 +5189,14 @@ buf_page_init_low( /** Inits a page to the buffer buf_pool. @param[in,out] buf_pool buffer pool @param[in] page_id page id +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] block block to init */ static void buf_page_init( buf_pool_t* buf_pool, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, buf_block_t* block) { buf_page_t* hash_page; @@ -5263,14 +5264,11 @@ buf_page_init( ut_d(block->page.in_page_hash = TRUE); block->page.id = page_id; - block->page.size.copy_from(page_size); HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, page_id.fold(), &block->page); - if (page_size.is_compressed()) { - page_zip_set_size(&block->page.zip, page_size.physical()); - } + page_zip_set_size(&block->page.zip, zip_size); } /** Initialize a page for read to the buffer buf_pool. If the page is @@ -5284,6 +5282,7 @@ and the lock released later. @param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED @param[in] mode BUF_READ_IBUF_PAGES_ONLY, ... @param[in] page_id page id +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] unzip whether the uncompressed page is requested (for ROW_FORMAT=COMPRESSED) @return pointer to the block @@ -5293,7 +5292,7 @@ buf_page_init_for_read( dberr_t* err, ulint mode, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, bool unzip) { buf_block_t* block; @@ -5312,12 +5311,12 @@ buf_page_init_for_read( if (mode == BUF_READ_IBUF_PAGES_ONLY) { /* It is a read-ahead within an ibuf routine */ - ut_ad(!ibuf_bitmap_page(page_id, page_size)); + ut_ad(!ibuf_bitmap_page(page_id, zip_size)); ibuf_mtr_start(&mtr); - if (!recv_no_ibuf_operations && - !ibuf_page(page_id, page_size, &mtr)) { + if (!recv_no_ibuf_operations + && !ibuf_page(page_id, zip_size, &mtr)) { ibuf_mtr_commit(&mtr); @@ -5327,7 +5326,7 @@ buf_page_init_for_read( ut_ad(mode == BUF_READ_ANY_PAGE); } - if (page_size.is_compressed() && !unzip && !recv_recovery_is_on()) { + if (zip_size && !unzip && !recv_recovery_is_on()) { block = NULL; } else { block = buf_LRU_get_free_block(buf_pool); @@ -5362,7 +5361,7 @@ buf_page_init_for_read( ut_ad(buf_pool_from_bpage(bpage) == buf_pool); - buf_page_init(buf_pool, page_id, page_size, block); + buf_page_init(buf_pool, page_id, zip_size, block); /* Note: We are using the hash_lock for protection. This is safe because no other thread can lookup the block from the @@ -5386,7 +5385,7 @@ buf_page_init_for_read( rw_lock_x_lock_gen(&block->lock, BUF_IO_READ); - if (page_size.is_compressed()) { + if (zip_size) { /* buf_pool->mutex may be released and reacquired by buf_buddy_alloc(). Thus, we must release block->mutex in order not to @@ -5396,8 +5395,7 @@ buf_page_init_for_read( been added to buf_pool->LRU and buf_pool->page_hash. */ buf_page_mutex_exit(block); - data = buf_buddy_alloc(buf_pool, page_size.physical(), - &lru); + data = buf_buddy_alloc(buf_pool, zip_size, &lru); buf_page_mutex_enter(block); block->page.zip.data = (page_zip_t*) data; @@ -5418,7 +5416,7 @@ buf_page_init_for_read( control block (bpage), in order to avoid the invocation of buf_buddy_relocate_block() on uninitialized data. */ - data = buf_buddy_alloc(buf_pool, page_size.physical(), &lru); + data = buf_buddy_alloc(buf_pool, zip_size, &lru); rw_lock_x_lock(hash_lock); @@ -5436,8 +5434,7 @@ buf_page_init_for_read( /* The block was added by some other thread. */ rw_lock_x_unlock(hash_lock); watch_page = NULL; - buf_buddy_free(buf_pool, data, - page_size.physical()); + buf_buddy_free(buf_pool, data, zip_size); bpage = NULL; goto func_exit; @@ -5450,13 +5447,11 @@ buf_page_init_for_read( bpage->buf_pool_index = buf_pool_index(buf_pool); page_zip_des_init(&bpage->zip); - page_zip_set_size(&bpage->zip, page_size.physical()); + page_zip_set_size(&bpage->zip, zip_size); bpage->zip.data = (page_zip_t*) data; - bpage->size.copy_from(page_size); - mutex_enter(&buf_pool->zip_mutex); - UNIV_MEM_DESC(bpage->zip.data, bpage->size.physical()); + UNIV_MEM_DESC(bpage->zip.data, zip_size); buf_page_init_low(bpage); @@ -5520,18 +5515,18 @@ func_exit: return(bpage); } -/** Initializes a page to the buffer buf_pool. The page is usually not read +/** Initialize a page in the buffer pool. The page is usually not read from a file even if it cannot be found in the buffer buf_pool. This is one of the functions which perform to a block a state transition NOT_USED => FILE_PAGE (the other is buf_page_get_gen). @param[in] page_id page id -@param[in] page_size page size -@param[in] mtr mini-transaction +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in,out] mtr mini-transaction @return pointer to the block, page bufferfixed */ buf_block_t* buf_page_create( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, mtr_t* mtr) { buf_frame_t* frame; @@ -5541,7 +5536,7 @@ buf_page_create( rw_lock_t* hash_lock; ut_ad(mtr->is_active()); - ut_ad(page_id.space() != 0 || !page_size.is_compressed()); + ut_ad(page_id.space() != 0 || !zip_size); free_block = buf_LRU_get_free_block(buf_pool); @@ -5568,7 +5563,7 @@ buf_page_create( buf_block_free(free_block); - return(buf_page_get_with_no_latch(page_id, page_size, mtr)); + return buf_page_get_with_no_latch(page_id, zip_size, mtr); } /* If we get here, the page was not in buf_pool: init it there */ @@ -5580,7 +5575,7 @@ buf_page_create( buf_page_mutex_enter(block); - buf_page_init(buf_pool, page_id, page_size, block); + buf_page_init(buf_pool, page_id, zip_size, block); rw_lock_x_unlock(hash_lock); @@ -5590,7 +5585,7 @@ buf_page_create( buf_block_buf_fix_inc(block, __FILE__, __LINE__); buf_pool->stat.n_pages_created++; - if (page_size.is_compressed()) { + if (zip_size) { void* data; bool lru; @@ -5608,7 +5603,7 @@ buf_page_create( the reacquisition of buf_pool->mutex. We also must defer this operation until after the block descriptor has been added to buf_pool->LRU and buf_pool->page_hash. */ - data = buf_buddy_alloc(buf_pool, page_size.physical(), &lru); + data = buf_buddy_alloc(buf_pool, zip_size, &lru); buf_page_mutex_enter(block); block->page.zip.data = (page_zip_t*) data; @@ -5634,7 +5629,7 @@ buf_page_create( /* Delete possible entries for the page from the insert buffer: such can exist if the page belonged to an index which was dropped */ - ibuf_merge_or_delete_for_page(NULL, page_id, &page_size, TRUE); + ibuf_merge_or_delete_for_page(NULL, page_id, zip_size, true); frame = block->frame; @@ -5844,13 +5839,14 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space) && space->crypt_data && space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED && !bpage->encrypted - && fil_space_verify_crypt_checksum(dst_frame, bpage->size); + && fil_space_verify_crypt_checksum(dst_frame, + bpage->zip_size()); if (!still_encrypted) { /* If traditional checksums match, we assume that page is not anymore encrypted. */ corrupted = buf_page_is_corrupted( - true, dst_frame, bpage->size, space); + true, dst_frame, bpage->zip_size(), space); if (!corrupted) { bpage->encrypted = false; @@ -5921,7 +5917,7 @@ buf_page_io_complete(buf_page_t* bpage, bool dblwr, bool evict) io_type = buf_page_get_io_fix(bpage); ut_ad(io_type == BUF_IO_READ || io_type == BUF_IO_WRITE); - ut_ad(bpage->size.is_compressed() == (bpage->zip.data != NULL)); + ut_ad(!!bpage->zip.ssize == (bpage->zip.data != NULL)); ut_ad(uncompressed || bpage->zip.data); if (io_type == BUF_IO_READ) { @@ -6021,7 +6017,7 @@ database_corrupted: << ". You may have to recover from " << "a backup."; - buf_page_print(frame, bpage->size); + buf_page_print(frame, bpage->zip_size()); ib::info() << "It is also possible that your" @@ -6085,7 +6081,7 @@ database_corrupted: ibuf_merge_or_delete_for_page( (buf_block_t*) bpage, bpage->id, - &bpage->size, TRUE); + bpage->zip_size(), true); } } @@ -7314,7 +7310,7 @@ buf_page_encrypt_before_write( return src_frame; } - ut_ad(!bpage->size.is_compressed() || !page_compressed); + ut_ad(!bpage->zip_size() || !page_compressed); buf_pool_t* buf_pool = buf_pool_from_bpage(bpage); /* Find free slot from temporary memory array */ buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool); @@ -7382,7 +7378,7 @@ bool buf_page_should_punch_hole( const buf_page_t* bpage) { - return (bpage->real_size != bpage->size.physical()); + return bpage->real_size != bpage->physical_size(); } /** @@ -7395,6 +7391,6 @@ buf_page_get_trim_length( const buf_page_t* bpage, ulint write_length) { - return (bpage->size.physical() - write_length); + return bpage->physical_size() - write_length; } #endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 0eaa746deb8..502aed20343 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -85,7 +85,7 @@ buf_dblwr_get( buf_block_t* block; block = buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO), - univ_page_size, RW_X_LATCH, mtr); + 0, RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); @@ -580,12 +580,13 @@ buf_dblwr_process() continue; } - const page_size_t page_size(space->flags); - ut_ad(!buf_page_is_zeroes(page, page_size.physical())); + const ulint physical_size = space->physical_size(); + const ulint zip_size = space->zip_size(); + ut_ad(!buf_page_is_zeroes(page, physical_size)); /* We want to ensure that for partial reads the unread portion of the page is NUL. */ - memset(read_buf, 0x0, page_size.physical()); + memset(read_buf, 0x0, physical_size); IORequest request; @@ -594,8 +595,8 @@ buf_dblwr_process() /* Read in the actual page from the file */ dberr_t err = fil_io( request, true, - page_id, page_size, - 0, page_size.physical(), read_buf, NULL); + page_id, zip_size, + 0, physical_size, read_buf, NULL); if (err != DB_SUCCESS) { ib::warn() @@ -605,7 +606,7 @@ buf_dblwr_process() } const bool is_all_zero = buf_page_is_zeroes( - read_buf, page_size.physical()); + read_buf, physical_size); const bool expect_encrypted = space->crypt_data && space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED; @@ -618,8 +619,7 @@ buf_dblwr_process() /* Decompress the page before validating the checksum. */ ulint decomp = fil_page_decompress(buf, read_buf); - if (!decomp || (decomp != srv_page_size - && page_size.is_compressed())) { + if (!decomp || (zip_size && decomp != srv_page_size)) { goto bad; } @@ -627,9 +627,9 @@ buf_dblwr_process() read_buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) ? fil_space_verify_crypt_checksum(read_buf, - page_size) + zip_size) : !buf_page_is_corrupted(true, read_buf, - page_size, space)) { + zip_size, space)) { /* The page is good; there is no need to consult the doublewrite buffer. */ continue; @@ -644,15 +644,14 @@ bad: } ulint decomp = fil_page_decompress(buf, page); - if (!decomp || (decomp != srv_page_size - && page_size.is_compressed())) { + if (!decomp || (zip_size && decomp != srv_page_size)) { goto bad_doublewrite; } if (expect_encrypted && mach_read_from_4( page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) - ? !fil_space_verify_crypt_checksum(page, page_size) - : buf_page_is_corrupted(true, page, page_size, space)) { + ? !fil_space_verify_crypt_checksum(page, zip_size) + : buf_page_is_corrupted(true, page, zip_size, space)) { if (!is_all_zero) { bad_doublewrite: ib::warn() << "A doublewrite copy of page " @@ -686,8 +685,8 @@ bad_doublewrite: IORequest write_request(IORequest::WRITE); - fil_io(write_request, true, page_id, page_size, - 0, page_size.physical(), + fil_io(write_request, true, page_id, zip_size, + 0, physical_size, const_cast(page), NULL); ib::info() << "Recovered page " << page_id @@ -834,7 +833,7 @@ buf_dblwr_assert_on_corrupt_block( /*==============================*/ const buf_block_t* block) /*!< in: block to check */ { - buf_page_print(block->frame, univ_page_size); + buf_page_print(block->frame); ib::fatal() << "Apparent corruption of an index page " << block->page.id @@ -924,14 +923,14 @@ buf_dblwr_write_block_to_datafile( void * frame = buf_page_get_frame(bpage); if (bpage->zip.data != NULL) { - ut_ad(bpage->size.is_compressed()); + ut_ad(bpage->zip_size()); - fil_io(request, sync, bpage->id, bpage->size, 0, - bpage->size.physical(), + fil_io(request, sync, bpage->id, bpage->zip_size(), 0, + bpage->zip_size(), (void*) frame, (void*) bpage); } else { - ut_ad(!bpage->size.is_compressed()); + ut_ad(!bpage->zip_size()); /* Our IO API is common for both reads and writes and is therefore geared towards a non-const parameter. */ @@ -943,8 +942,8 @@ buf_dblwr_write_block_to_datafile( buf_dblwr_check_page_lsn(block->frame); fil_io(request, - sync, bpage->id, bpage->size, 0, bpage->real_size, - frame, block); + sync, bpage->id, bpage->zip_size(), 0, bpage->real_size, + frame, block); } } @@ -1045,7 +1044,7 @@ try_again: buf_dblwr->first_free) << srv_page_size_shift; fil_io(IORequestWrite, true, - page_id_t(TRX_SYS_SPACE, buf_dblwr->block1), univ_page_size, + page_id_t(TRX_SYS_SPACE, buf_dblwr->block1), 0, 0, len, (void*) write_buf, NULL); if (buf_dblwr->first_free <= TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { @@ -1061,7 +1060,7 @@ try_again: + (TRX_SYS_DOUBLEWRITE_BLOCK_SIZE << srv_page_size_shift); fil_io(IORequestWrite, true, - page_id_t(TRX_SYS_SPACE, buf_dblwr->block2), univ_page_size, + page_id_t(TRX_SYS_SPACE, buf_dblwr->block2), 0, 0, len, (void*) write_buf, NULL); flush: @@ -1146,21 +1145,16 @@ try_again: encryption and/or page compression */ void * frame = buf_page_get_frame(bpage); - if (bpage->size.is_compressed()) { - UNIV_MEM_ASSERT_RW(bpage->zip.data, bpage->size.physical()); + if (auto zip_size = bpage->zip_size()) { + UNIV_MEM_ASSERT_RW(bpage->zip.data, zip_size); /* Copy the compressed page and clear the rest. */ - - memcpy(p, frame, bpage->size.physical()); - - memset(p + bpage->size.physical(), 0x0, - srv_page_size - bpage->size.physical()); + memcpy(p, frame, zip_size); + memset(p + zip_size, 0x0, srv_page_size - zip_size); } else { ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); - UNIV_MEM_ASSERT_RW(frame, - bpage->size.logical()); - - memcpy(p, frame, bpage->size.logical()); + UNIV_MEM_ASSERT_RW(frame, srv_page_size); + memcpy(p, frame, srv_page_size); } buf_dblwr->buf_block_arr[buf_dblwr->first_free] = bpage; @@ -1282,18 +1276,18 @@ retry: encryption and/or page compression */ void * frame = buf_page_get_frame(bpage); - if (bpage->size.is_compressed()) { + if (auto zip_size = bpage->zip_size()) { memcpy(buf_dblwr->write_buf + srv_page_size * i, - frame, bpage->size.physical()); + frame, zip_size); memset(buf_dblwr->write_buf + srv_page_size * i - + bpage->size.physical(), 0x0, - srv_page_size - bpage->size.physical()); + + zip_size, 0x0, + srv_page_size - zip_size); fil_io(IORequestWrite, true, page_id_t(TRX_SYS_SPACE, offset), - univ_page_size, + 0, 0, srv_page_size, (void *)(buf_dblwr->write_buf + srv_page_size * i), @@ -1304,7 +1298,7 @@ retry: fil_io(IORequestWrite, true, page_id_t(TRX_SYS_SPACE, offset), - univ_page_size, + 0, 0, srv_page_size, (void*) frame, diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 2747a6fa338..2fc700307ab 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -672,7 +672,7 @@ buf_load() so all pages from a given tablespace are consecutive. */ ulint cur_space_id = BUF_DUMP_SPACE(dump[0]); fil_space_t* space = fil_space_acquire_silent(cur_space_id); - page_size_t page_size(space ? space->flags : 0); + ulint zip_size = space ? space->zip_size() : 0; /* JAN: TODO: MySQL 5.7 PSI #ifdef HAVE_PSI_STAGE_INTERFACE @@ -703,9 +703,7 @@ buf_load() space = fil_space_acquire_silent(cur_space_id); if (space != NULL) { - const page_size_t cur_page_size( - space->flags); - page_size.copy_from(cur_page_size); + zip_size = space->zip_size(); } } @@ -720,7 +718,7 @@ buf_load() buf_read_page_background( page_id_t(this_space_id, BUF_DUMP_PAGE(dump[i])), - page_size, true); + zip_size, true); if (i % 64 == 63) { os_aio_simulated_wake_handler_threads(); diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index ac8dd98dbe1..f1d6398e772 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -211,7 +211,7 @@ incr_flush_list_size_in_bytes( { ut_ad(buf_flush_list_mutex_own(buf_pool)); - buf_pool->stat.flush_list_bytes += block->page.size.physical(); + buf_pool->stat.flush_list_bytes += block->physical_size(); ut_ad(buf_pool->stat.flush_list_bytes <= buf_pool->curr_pool_size); } @@ -433,7 +433,7 @@ buf_flush_insert_into_flush_list( block->page.oldest_modification = lsn; UNIV_MEM_ASSERT_RW(block->page.zip.data ? block->page.zip.data : block->frame, - block->page.size.physical()); + block->physical_size()); incr_flush_list_size_in_bytes(block, buf_pool); if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) { @@ -601,7 +601,7 @@ buf_flush_remove( because we assert on in_flush_list in comparison function. */ ut_d(bpage->in_flush_list = FALSE); - buf_pool->stat.flush_list_bytes -= bpage->size.physical(); + buf_pool->stat.flush_list_bytes -= bpage->physical_size(); bpage->oldest_modification = 0; @@ -977,7 +977,7 @@ buf_flush_write_block_low( mach_write_to_8(frame + FIL_PAGE_LSN, bpage->newest_modification); - ut_a(page_zip_verify_checksum(frame, bpage->size.physical())); + ut_a(page_zip_verify_checksum(frame, bpage->zip_size())); break; case BUF_BLOCK_FILE_PAGE: frame = bpage->zip.data; @@ -1004,7 +1004,8 @@ buf_flush_write_block_low( /* TODO: pass the tablespace to fil_io() */ fil_io(request, - sync, bpage->id, bpage->size, 0, bpage->size.physical(), + sync, bpage->id, bpage->zip_size(), 0, + bpage->physical_size(), frame, bpage); } else { ut_ad(!srv_read_only_mode); diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 9baa299910a..e0acd1cfeed 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -166,7 +166,7 @@ incr_LRU_size_in_bytes( { ut_ad(buf_pool_mutex_own(buf_pool)); - buf_pool->stat.LRU_bytes += bpage->size.physical(); + buf_pool->stat.LRU_bytes += bpage->physical_size(); ut_ad(buf_pool->stat.LRU_bytes <= buf_pool->curr_pool_size); } @@ -1389,7 +1389,7 @@ buf_LRU_remove_block( UT_LIST_REMOVE(buf_pool->LRU, bpage); ut_d(bpage->in_LRU_list = FALSE); - buf_pool->stat.LRU_bytes -= bpage->size.physical(); + buf_pool->stat.LRU_bytes -= bpage->physical_size(); buf_unzip_LRU_remove_block_if_needed(bpage); @@ -1661,9 +1661,9 @@ func_exit: ? BUF_BLOCK_ZIP_DIRTY : BUF_BLOCK_ZIP_PAGE; - ut_ad(b->size.is_compressed()); + ut_ad(b->zip_size()); - UNIV_MEM_DESC(b->zip.data, b->size.physical()); + UNIV_MEM_DESC(b->zip.data, b->zip_size()); /* The fields in_page_hash and in_LRU_list of the to-be-freed block descriptor should have @@ -1742,10 +1742,6 @@ func_exit: page_zip_set_size(&bpage->zip, 0); - bpage->size.copy_from(page_size_t(bpage->size.logical(), - bpage->size.logical(), - false)); - mutex_exit(block_mutex); /* Prevent buf_page_get_gen() from @@ -1785,11 +1781,11 @@ func_exit: buf_pool->page_hash, thus inaccessible by any other thread. */ - ut_ad(b->size.is_compressed()); + ut_ad(b->zip_size()); const uint32_t checksum = page_zip_calc_checksum( b->zip.data, - b->size.physical(), + b->zip_size(), static_cast( srv_checksum_algorithm)); @@ -1856,19 +1852,14 @@ buf_LRU_block_free_non_file_page( buf_page_mutex_exit(block); buf_pool_mutex_exit_forbid(buf_pool); - ut_ad(block->page.size.is_compressed()); + ut_ad(block->zip_size()); - buf_buddy_free(buf_pool, data, block->page.size.physical()); + buf_buddy_free(buf_pool, data, block->zip_size()); buf_pool_mutex_exit_allow(buf_pool); buf_page_mutex_enter(block); page_zip_set_size(&block->page.zip, 0); - - block->page.size.copy_from( - page_size_t(block->page.size.logical(), - block->page.size.logical(), - false)); } if (buf_pool->curr_size < buf_pool->old_size @@ -1939,7 +1930,7 @@ buf_LRU_block_remove_hashed( const page_t* page = ((buf_block_t*) bpage)->frame; ut_a(!zip || bpage->oldest_modification == 0); - ut_ad(bpage->size.is_compressed()); + ut_ad(bpage->zip_size()); switch (fil_page_get_type(page)) { case FIL_PAGE_TYPE_ALLOCATED: @@ -1954,7 +1945,7 @@ buf_LRU_block_remove_hashed( to the compressed page, which will be preserved. */ memcpy(bpage->zip.data, page, - bpage->size.physical()); + bpage->zip_size()); } break; case FIL_PAGE_TYPE_ZBLOB: @@ -1971,14 +1962,13 @@ buf_LRU_block_remove_hashed( default: ib::error() << "The compressed page to be" " evicted seems corrupt:"; - ut_print_buf(stderr, page, - bpage->size.logical()); + ut_print_buf(stderr, page, srv_page_size); ib::error() << "Possibly older version of" " the page:"; ut_print_buf(stderr, bpage->zip.data, - bpage->size.physical()); + bpage->zip_size()); putc('\n', stderr); ut_error; } @@ -1988,10 +1978,7 @@ buf_LRU_block_remove_hashed( /* fall through */ case BUF_BLOCK_ZIP_PAGE: ut_a(bpage->oldest_modification == 0); - if (bpage->size.is_compressed()) { - UNIV_MEM_ASSERT_W(bpage->zip.data, - bpage->size.physical()); - } + UNIV_MEM_ASSERT_W(bpage->zip.data, bpage->zip_size()); break; case BUF_BLOCK_POOL_WATCH: case BUF_BLOCK_ZIP_DIRTY: @@ -2007,25 +1994,16 @@ buf_LRU_block_remove_hashed( if (bpage != hashed_bpage) { ib::error() << "Page " << bpage->id << " not found in the hash table"; - -#ifdef UNIV_DEBUG - - ib::error() +#ifdef UNIV_DEBUG << "in_page_hash:" << bpage->in_page_hash << " in_zip_hash:" << bpage->in_zip_hash - // << " in_free_list:"<< bpage->in_fee_list << " in_flush_list:" << bpage->in_flush_list << " in_LRU_list:" << bpage->in_LRU_list - << " zip.data:" << bpage->zip.data - << " zip_size:" << bpage->size.logical() - << " page_state:" << buf_page_get_state(bpage); -#else - ib::error() - << " zip.data:" << bpage->zip.data - << " zip_size:" << bpage->size.logical() - << " page_state:" << buf_page_get_state(bpage); #endif + << " zip.data:" << bpage->zip.data + << " zip_size:" << bpage->zip_size() + << " page_state:" << buf_page_get_state(bpage); if (hashed_bpage) { @@ -2059,7 +2037,7 @@ buf_LRU_block_remove_hashed( ut_ad(!bpage->in_flush_list); ut_ad(!bpage->in_LRU_list); ut_a(bpage->zip.data); - ut_a(bpage->size.is_compressed()); + ut_a(bpage->zip.ssize); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG UT_LIST_REMOVE(buf_pool->zip_clean, bpage); @@ -2069,8 +2047,7 @@ buf_LRU_block_remove_hashed( rw_lock_x_unlock(hash_lock); buf_pool_mutex_exit_forbid(buf_pool); - buf_buddy_free(buf_pool, bpage->zip.data, - bpage->size.physical()); + buf_buddy_free(buf_pool, bpage->zip.data, bpage->zip_size()); buf_pool_mutex_exit_allow(buf_pool); buf_page_free_descriptor(bpage); @@ -2117,16 +2094,11 @@ buf_LRU_block_remove_hashed( ut_ad(!bpage->in_LRU_list); buf_pool_mutex_exit_forbid(buf_pool); - buf_buddy_free(buf_pool, data, bpage->size.physical()); + buf_buddy_free(buf_pool, data, bpage->zip_size()); buf_pool_mutex_exit_allow(buf_pool); page_zip_set_size(&bpage->zip, 0); - - bpage->size.copy_from( - page_size_t(bpage->size.logical(), - bpage->size.logical(), - false)); } return(true); @@ -2484,7 +2456,7 @@ buf_LRU_print_instance( fprintf(stderr, "\ntype %u size " ULINTPF " index id " IB_ID_FMT "\n", fil_page_get_type(frame), - bpage->size.physical(), + bpage->zip_size(), btr_page_get_index_id(frame)); break; diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc index 9454b57f59e..f4271c8d738 100644 --- a/storage/innobase/buf/buf0rea.cc +++ b/storage/innobase/buf/buf0rea.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -102,6 +102,7 @@ flag is cleared and the x-lock released by an i/o-handler thread. @param[in] type IO type, SIMULATED, IGNORE_MISSING @param[in] mode BUF_READ_IBUF_PAGES_ONLY, ..., @param[in] page_id page id +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] unzip true=request uncompressed page @param[in] ignore_missing_space true=ignore missing space when reading @return 1 if a read request was queued, 0 if the page already resided @@ -116,7 +117,7 @@ buf_read_page_low( ulint type, ulint mode, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, bool unzip, bool ignore_missing_space = false) { @@ -132,7 +133,7 @@ buf_read_page_low( return(0); } - if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) { + if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) { /* Trx sys header is so low in the latching order that we play safe and do not leave the i/o-completion to an asynchronous @@ -147,7 +148,7 @@ buf_read_page_low( or is being dropped; if we succeed in initing the page in the buffer pool for read, then DISCARD cannot proceed until the read has completed */ - bpage = buf_page_init_for_read(err, mode, page_id, page_size, unzip); + bpage = buf_page_init_for_read(err, mode, page_id, zip_size, unzip); if (bpage == NULL) { @@ -155,7 +156,7 @@ buf_read_page_low( } DBUG_LOG("ib_buf", - "read page " << page_id << " size=" << page_size.physical() + "read page " << page_id << " zip_size=" << zip_size << " unzip=" << unzip << ',' << (sync ? "sync" : "async")); ut_ad(buf_page_in_file(bpage)); @@ -166,7 +167,7 @@ buf_read_page_low( void* dst; - if (page_size.is_compressed()) { + if (zip_size) { dst = bpage->zip.data; } else { ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); @@ -177,7 +178,8 @@ buf_read_page_low( IORequest request(type | IORequest::READ); *err = fil_io( - request, sync, page_id, page_size, 0, page_size.physical(), + request, sync, page_id, zip_size, 0, + zip_size ? zip_size : srv_page_size, dst, bpage, ignore_missing_space); if (sync) { @@ -218,16 +220,13 @@ performed by ibuf routines, a situation which could result in a deadlock if the OS does not support asynchronous i/o. @param[in] page_id page id of a page which the current thread wants to access -@param[in] page_size page size -@param[in] inside_ibuf TRUE if we are inside ibuf routine +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in] ibuf whether we are inside ibuf routine @return number of page read requests issued; NOTE that if we read ibuf pages, it may happen that the page at the given page number does not get read even if we return a positive value! */ ulint -buf_read_ahead_random( - const page_id_t page_id, - const page_size_t& page_size, - ibool inside_ibuf) +buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf) { buf_pool_t* buf_pool = buf_pool_get(page_id); ulint recent_blocks = 0; @@ -249,7 +248,7 @@ buf_read_ahead_random( return(0); } - if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) { + if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) { /* If it is an ibuf bitmap page or trx sys hdr, we do no read-ahead, as that could break the ibuf page access @@ -264,14 +263,14 @@ buf_read_ahead_random( high = (page_id.page_no() / buf_read_ahead_random_area + 1) * buf_read_ahead_random_area; - /* Remember the tablespace version before we ask the tablespace size - below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we + /* If DISCARD + IMPORT changes the actual .ibd file meanwhile, we do not try to read outside the bounds of the tablespace! */ if (fil_space_t* space = fil_space_acquire(page_id.space())) { #ifdef UNIV_DEBUG if (srv_file_per_table) { ulint size = 0; + const ulint physical_size = space->physical_size(); for (const fil_node_t* node = UT_LIST_GET_FIRST(space->chain); @@ -279,7 +278,7 @@ buf_read_ahead_random( node = UT_LIST_GET_NEXT(chain, node)) { size += ulint(os_file_get_size(node->handle) - / page_size.physical()); + / physical_size); } ut_ad(size == space->size); @@ -332,12 +331,7 @@ buf_read_ahead_random( read_ahead: /* Read all the suitable blocks within the area */ - if (inside_ibuf) { - ibuf_mode = BUF_READ_IBUF_PAGES_ONLY; - } else { - ibuf_mode = BUF_READ_ANY_PAGE; - } - + ibuf_mode = ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE; count = 0; for (i = low; i < high; i++) { @@ -346,12 +340,12 @@ read_ahead: const page_id_t cur_page_id(page_id.space(), i); - if (!ibuf_bitmap_page(cur_page_id, page_size)) { + if (!ibuf_bitmap_page(cur_page_id, zip_size)) { count += buf_read_page_low( &err, false, IORequest::DO_NOT_WAKE, ibuf_mode, - cur_page_id, page_size, false); + cur_page_id, zip_size, false); switch (err) { case DB_SUCCESS: @@ -396,16 +390,13 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets an exclusive lock on the buffer frame. The flag is cleared and the x-lock released by the i/o-handler thread. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @retval DB_SUCCESS if the page was read and is not corrupted, @retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted, @retval DB_DECRYPTION_FAILED if page post encryption checksum matches but after decryption normal page checksum does not match. @retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */ -dberr_t -buf_read_page( - const page_id_t page_id, - const page_size_t& page_size) +dberr_t buf_read_page(const page_id_t page_id, ulint zip_size) { ulint count; dberr_t err = DB_SUCCESS; @@ -418,7 +409,7 @@ buf_read_page( count = buf_read_page_low( &err, true, - 0, BUF_READ_ANY_PAGE, page_id, page_size, false); + 0, BUF_READ_ANY_PAGE, page_id, zip_size, false); srv_stats.buf_pool_reads.add(count); @@ -438,13 +429,10 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets an exclusive lock on the buffer frame. The flag is cleared and the x-lock released by the i/o-handler thread. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] sync true if synchronous aio is desired */ void -buf_read_page_background( - const page_id_t page_id, - const page_size_t& page_size, - bool sync) +buf_read_page_background(const page_id_t page_id, ulint zip_size, bool sync) { ulint count; dberr_t err; @@ -453,7 +441,7 @@ buf_read_page_background( &err, sync, IORequest::DO_NOT_WAKE | IORequest::IGNORE_MISSING, BUF_READ_ANY_PAGE, - page_id, page_size, false); + page_id, zip_size, false); switch (err) { case DB_SUCCESS: @@ -508,14 +496,11 @@ NOTE 3: the calling thread must want access to the page given: this rule is set to prevent unintended read-aheads performed by ibuf routines, a situation which could result in a deadlock if the OS does not support asynchronous io. @param[in] page_id page id; see NOTE 3 above -@param[in] page_size page size -@param[in] inside_ibuf TRUE if we are inside ibuf routine +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in] ibuf whether if we are inside ibuf routine @return number of page read requests issued */ ulint -buf_read_ahead_linear( - const page_id_t page_id, - const page_size_t& page_size, - ibool inside_ibuf) +buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf) { buf_pool_t* buf_pool = buf_pool_get(page_id); buf_page_t* bpage; @@ -554,7 +539,7 @@ buf_read_ahead_linear( return(0); } - if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) { + if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) { /* If it is an ibuf bitmap page or trx sys hdr, we do no read-ahead, as that could break the ibuf page access @@ -715,9 +700,7 @@ buf_read_ahead_linear( /* If we got this far, read-ahead can be sensible: do it */ - ulint ibuf_mode; - - ibuf_mode = inside_ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE; + ulint ibuf_mode = ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE; /* Since Windows XP seems to schedule the i/o handler thread very eagerly, and consequently it does not wait for the @@ -731,11 +714,11 @@ buf_read_ahead_linear( const page_id_t cur_page_id(page_id.space(), i); - if (!ibuf_bitmap_page(cur_page_id, page_size)) { + if (!ibuf_bitmap_page(cur_page_id, zip_size)) { count += buf_read_page_low( &err, false, IORequest::DO_NOT_WAKE, - ibuf_mode, cur_page_id, page_size, false); + ibuf_mode, cur_page_id, zip_size, false); switch (err) { case DB_SUCCESS: @@ -801,11 +784,8 @@ buf_read_ibuf_merge_pages( #endif for (ulint i = 0; i < n_stored; i++) { - bool found; - const page_size_t page_size(fil_space_get_page_size( - space_ids[i], &found)); - - if (!found) { + fil_space_t* s = fil_space_acquire_for_io(space_ids[i]); + if (!s) { tablespace_deleted: /* The tablespace was not found: remove all entries for it */ @@ -817,6 +797,9 @@ tablespace_deleted: continue; } + const ulint zip_size = s->zip_size(); + s->release_for_io(); + const page_id_t page_id(space_ids[i], page_nos[i]); buf_pool_t* buf_pool = buf_pool_get(page_id); @@ -831,7 +814,7 @@ tablespace_deleted: buf_read_page_low(&err, sync && (i + 1 == n_stored), 0, - BUF_READ_ANY_PAGE, page_id, page_size, + BUF_READ_ANY_PAGE, page_id, zip_size, true, true /* ignore_missing_space */); switch(err) { @@ -882,7 +865,7 @@ buf_read_recv_pages( fil_space_open_if_needed(space); - const page_size_t page_size(space->flags); + const ulint zip_size = space->zip_size(); for (ulint i = 0; i < n_stored; i++) { buf_pool_t* buf_pool; @@ -915,13 +898,13 @@ buf_read_recv_pages( &err, true, 0, BUF_READ_ANY_PAGE, - cur_page_id, page_size, true); + cur_page_id, zip_size, true); } else { buf_read_page_low( &err, false, IORequest::DO_NOT_WAKE, BUF_READ_ANY_PAGE, - cur_page_id, page_size, true); + cur_page_id, zip_size, true); } if (err == DB_DECRYPTION_FAILED || err == DB_PAGE_CORRUPTED) { diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc index 9474b9bd18b..a95b56d2247 100644 --- a/storage/innobase/data/data0data.cc +++ b/storage/innobase/data/data0data.cc @@ -610,6 +610,12 @@ dtuple_convert_big_rec( return(NULL); } + if (!index->table->space) { + return NULL; + } + + const auto zip_size = index->table->space->zip_size(); + ut_ad(index->n_uniq > 0); ut_a(dtuple_check_typed_no_assert(entry)); @@ -660,7 +666,7 @@ dtuple_convert_big_rec( *n_ext), index->table->not_redundant(), dict_index_get_n_fields(index), - dict_table_page_size(index->table))) { + zip_size)) { longest_i = 0; for (ulint i = index->first_user_field(), longest = 0; i + mblob < entry->n_fields; i++) { diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index 7a9b8556c1a..2a80def7335 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -47,7 +47,7 @@ dict_hdr_get( dict_hdr_t* header; block = buf_page_get(page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO), - univ_page_size, RW_X_LATCH, mtr); + 0, RW_X_LATCH, mtr); header = DICT_HDR + buf_block_get_frame(block); buf_block_dbg_add_level(block, SYNC_DICT_HEADER); diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index b1ddb7032ab..d8b9bcdaf39 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -960,21 +960,19 @@ dict_drop_index_tree( ut_ad(len == 8); - bool found; - const page_size_t page_size(fil_space_get_page_size(space, - &found)); - - if (!found) { - /* It is a single table tablespace and the .ibd file is - missing: do nothing */ - - return(false); + if (fil_space_t* s = fil_space_acquire_silent(space)) { + /* Ensure that the tablespace file exists + in order to avoid a crash in buf_page_get_gen(). */ + if (s->size || fil_space_get_size(space)) { + btr_free_if_exists(page_id_t(space, root_page_no), + s->zip_size(), + mach_read_from_8(ptr), mtr); + } + s->release(); + return true; } - btr_free_if_exists(page_id_t(space, root_page_no), page_size, - mach_read_from_8(ptr), mtr); - - return(true); + return false; } /*******************************************************************//** diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 4ea5a5b30e9..7664bc2064d 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2118,10 +2118,9 @@ dict_index_too_big_for_tree( comp = dict_table_is_comp(table); - const page_size_t page_size(dict_tf_get_page_size(table->flags)); + const ulint zip_size = dict_tf_get_zip_size(table->flags); - if (page_size.is_compressed() - && page_size.physical() < srv_page_size) { + if (zip_size && zip_size < srv_page_size) { /* On a compressed page, two records must fit in the uncompressed page modification log. On compressed pages with size.physical() == srv_page_size, @@ -2132,7 +2131,7 @@ dict_index_too_big_for_tree( number in the page modification log. The maximum allowed node pointer size is half that. */ page_rec_max = page_zip_empty_size(new_index->n_fields, - page_size.physical()); + zip_size); if (page_rec_max) { page_rec_max--; } @@ -7073,52 +7072,3 @@ dict_space_get_id( return(id); } - -/** Determine the extent size (in pages) for the given table -@param[in] table the table whose extent size is being - calculated. -@return extent size in pages (256, 128 or 64) */ -ulint -dict_table_extent_size( - const dict_table_t* table) -{ - const ulint mb_1 = 1024 * 1024; - const ulint mb_2 = 2 * mb_1; - const ulint mb_4 = 4 * mb_1; - - page_size_t page_size = dict_table_page_size(table); - ulint pages_in_extent = FSP_EXTENT_SIZE; - - if (page_size.is_compressed()) { - - ulint disk_page_size = page_size.physical(); - - switch (disk_page_size) { - case 1024: - pages_in_extent = mb_1/1024; - break; - case 2048: - pages_in_extent = mb_1/2048; - break; - case 4096: - pages_in_extent = mb_1/4096; - break; - case 8192: - pages_in_extent = mb_1/8192; - break; - case 16384: - pages_in_extent = mb_1/16384; - break; - case 32768: - pages_in_extent = mb_2/32768; - break; - case 65536: - pages_in_extent = mb_4/65536; - break; - default: - ut_ad(0); - } - } - - return(pages_in_extent); -} diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index f236d2edadf..f4b05766e79 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1505,7 +1505,7 @@ dict_stats_analyze_index_below_cur( page_id_t page_id(index->table->space_id, btr_node_ptr_get_child_page_no( rec, offsets_rec)); - const page_size_t page_size(index->table->space->flags); + const ulint zip_size = index->table->space->zip_size(); /* assume no external pages by default - in case we quit from this function without analyzing any leaf pages */ @@ -1518,7 +1518,7 @@ dict_stats_analyze_index_below_cur( dberr_t err = DB_SUCCESS; - block = buf_page_get_gen(page_id, page_size, RW_S_LATCH, + block = buf_page_get_gen(page_id, zip_size, RW_S_LATCH, NULL /* no guessed block */, BUF_GET, __FILE__, __LINE__, &mtr, &err); diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index a30be6c5aed..b49bd5cc04d 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (c) 2014, 2018, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2014, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -274,16 +274,14 @@ fil_space_merge_crypt_data( } /** Initialize encryption parameters from a tablespace header page. -@param[in] page_size page size of the tablespace +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] page first page of the tablespace @return crypt data from page 0 @retval NULL if not present or not valid */ -UNIV_INTERN -fil_space_crypt_t* -fil_space_read_crypt_data(const page_size_t& page_size, const byte* page) +fil_space_crypt_t* fil_space_read_crypt_data(ulint zip_size, const byte* page) { const ulint offset = FSP_HEADER_OFFSET - + fsp_header_get_encryption_offset(page_size); + + fsp_header_get_encryption_offset(zip_size); if (memcmp(page + offset, CRYPT_MAGIC, MAGIC_SZ) != 0) { /* Crypt data is not stored. */ @@ -371,7 +369,7 @@ fil_space_crypt_t::write_page0( ut_ad(this == space->crypt_data); const uint len = sizeof(iv); const ulint offset = FSP_HEADER_OFFSET - + fsp_header_get_encryption_offset(page_size_t(space->flags)); + + fsp_header_get_encryption_offset(space->zip_size()); page0_offset = offset; /* @@ -545,7 +543,7 @@ fil_parse_write_crypt_data( @param[in] offset Page offset @param[in] lsn Log sequence number @param[in] src_frame Page to encrypt -@param[in] page_size Page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] dst_frame Output buffer @return encrypted buffer or NULL */ UNIV_INTERN @@ -556,10 +554,10 @@ fil_encrypt_buf( ulint offset, lsn_t lsn, const byte* src_frame, - const page_size_t& page_size, + ulint zip_size, byte* dst_frame) { - uint size = uint(page_size.physical()); + uint size = uint(zip_size ? zip_size : srv_page_size); uint key_version = fil_crypt_get_latest_key_version(crypt_data); ut_a(key_version != ENCRYPTION_KEY_VERSION_INVALID); @@ -601,24 +599,24 @@ fil_encrypt_buf( to sector boundary is written. */ if (!page_compressed) { /* FIL page trailer is also not encrypted */ - memcpy(dst_frame + page_size.physical() - FIL_PAGE_DATA_END, - src_frame + page_size.physical() - FIL_PAGE_DATA_END, + memcpy(dst_frame + size - FIL_PAGE_DATA_END, + src_frame + size - FIL_PAGE_DATA_END, FIL_PAGE_DATA_END); } else { /* Clean up rest of buffer */ memset(dst_frame+header_len+srclen, 0, - page_size.physical() - (header_len + srclen)); + size - (header_len + srclen)); } /* handle post encryption checksum */ ib_uint32_t checksum = 0; - checksum = fil_crypt_calculate_checksum(page_size, dst_frame); + checksum = fil_crypt_calculate_checksum(zip_size, dst_frame); // store the post-encryption checksum after the key-version mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, checksum); - ut_ad(fil_space_verify_crypt_checksum(dst_frame, page_size)); + ut_ad(fil_space_verify_crypt_checksum(dst_frame, zip_size)); srv_stats.pages_encrypted.inc(); @@ -657,10 +655,10 @@ fil_space_encrypt( } fil_space_crypt_t* crypt_data = space->crypt_data; - const page_size_t page_size(space->flags); + const ulint zip_size = space->zip_size(); ut_ad(space->pending_io()); byte* tmp = fil_encrypt_buf(crypt_data, space->id, offset, lsn, - src_frame, page_size, dst_frame); + src_frame, zip_size, dst_frame); #ifdef UNIV_DEBUG if (tmp) { @@ -681,8 +679,9 @@ fil_space_encrypt( } } - ut_ad(!buf_page_is_corrupted(true, src, page_size, space)); - ut_ad(fil_space_decrypt(crypt_data, tmp_mem, page_size, tmp, + ut_ad(!buf_page_is_corrupted(true, src, zip_size, space)); + ut_ad(fil_space_decrypt(crypt_data, tmp_mem, + space->physical_size(), tmp, &err)); ut_ad(err == DB_SUCCESS); @@ -696,7 +695,7 @@ fil_space_encrypt( memcpy(tmp_mem + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, src + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 8); - ut_ad(!memcmp(src, tmp_mem, page_size.physical())); + ut_ad(!memcmp(src, tmp_mem, space->physical_size())); } #endif /* UNIV_DEBUG */ @@ -706,7 +705,7 @@ fil_space_encrypt( /** Decrypt a page. @param[in] crypt_data crypt_data @param[in] tmp_frame Temporary buffer -@param[in] page_size Page size +@param[in] physical_size page size @param[in,out] src_frame Page to decrypt @param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED @return true if page decrypted, false if not.*/ @@ -715,7 +714,7 @@ bool fil_space_decrypt( fil_space_crypt_t* crypt_data, byte* tmp_frame, - const page_size_t& page_size, + ulint physical_size, byte* src_frame, dberr_t* err) { @@ -748,8 +747,7 @@ fil_space_decrypt( const byte* src = src_frame + header_len; byte* dst = tmp_frame + header_len; uint32 dstlen = 0; - uint srclen = uint(page_size.physical()) - - header_len - FIL_PAGE_DATA_END; + uint srclen = uint(physical_size) - header_len - FIL_PAGE_DATA_END; if (page_compressed) { srclen = mach_read_from_2(src_frame + FIL_PAGE_DATA); @@ -779,8 +777,8 @@ fil_space_decrypt( to sector boundary is written. */ if (!page_compressed) { /* Copy FIL trailer */ - memcpy(tmp_frame + page_size.physical() - FIL_PAGE_DATA_END, - src_frame + page_size.physical() - FIL_PAGE_DATA_END, + memcpy(tmp_frame + physical_size - FIL_PAGE_DATA_END, + src_frame + physical_size - FIL_PAGE_DATA_END, FIL_PAGE_DATA_END); } @@ -807,21 +805,21 @@ fil_space_decrypt( { dberr_t err = DB_SUCCESS; byte* res = NULL; - const page_size_t page_size(space->flags); + const ulint physical_size = space->physical_size(); *decrypted = false; ut_ad(space->crypt_data != NULL && space->crypt_data->is_encrypted()); ut_ad(space->pending_io()); bool encrypted = fil_space_decrypt(space->crypt_data, tmp_frame, - page_size, src_frame, &err); + physical_size, src_frame, &err); if (err == DB_SUCCESS) { if (encrypted) { *decrypted = true; /* Copy the decrypted page back to page buffer, not really any other options. */ - memcpy(src_frame, tmp_frame, page_size.physical()); + memcpy(src_frame, tmp_frame, physical_size); } res = src_frame; @@ -830,21 +828,18 @@ fil_space_decrypt( return res; } -/****************************************************************** +/** Calculate post encryption checksum -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] dst_frame Block where checksum is calculated @return page checksum not needed. */ -UNIV_INTERN uint32_t -fil_crypt_calculate_checksum( - const page_size_t& page_size, - const byte* dst_frame) +fil_crypt_calculate_checksum(ulint zip_size, const byte* dst_frame) { /* For encrypted tables we use only crc32 and strict_crc32 */ - return page_size.is_compressed() - ? page_zip_calc_checksum(dst_frame, page_size.physical(), + return zip_size + ? page_zip_calc_checksum(dst_frame, zip_size, SRV_CHECKSUM_ALGORITHM_CRC32) : buf_calc_page_crc32(dst_frame); } @@ -952,15 +947,15 @@ fil_crypt_read_crypt_data(fil_space_t* space) return; } - const page_size_t page_size(space->flags); + const ulint zip_size = space->zip_size(); mtr_t mtr; mtr.start(); if (buf_block_t* block = buf_page_get(page_id_t(space->id, 0), - page_size, RW_S_LATCH, &mtr)) { + zip_size, RW_S_LATCH, &mtr)) { mutex_enter(&fil_system.mutex); if (!space->crypt_data) { space->crypt_data = fil_space_read_crypt_data( - page_size, block->frame); + zip_size, block->frame); } mutex_exit(&fil_system.mutex); } @@ -1034,7 +1029,7 @@ fil_crypt_start_encrypting_space( /* 2 - get page 0 */ dberr_t err = DB_SUCCESS; buf_block_t* block = buf_page_get_gen( - page_id_t(space->id, 0), page_size_t(space->flags), + page_id_t(space->id, 0), space->zip_size(), RW_X_LATCH, NULL, BUF_GET, __FILE__, __LINE__, &mtr, &err); @@ -1623,7 +1618,7 @@ fil_crypt_get_page_throttle_func( unsigned line) { fil_space_t* space = state->space; - const page_size_t page_size = page_size_t(space->flags); + const ulint zip_size = space->zip_size(); const page_id_t page_id(space->id, offset); ut_ad(space->referenced()); @@ -1634,7 +1629,7 @@ fil_crypt_get_page_throttle_func( } dberr_t err = DB_SUCCESS; - buf_block_t* block = buf_page_get_gen(page_id, page_size, RW_X_LATCH, + buf_block_t* block = buf_page_get_gen(page_id, zip_size, RW_X_LATCH, NULL, BUF_PEEK_IF_IN_POOL, file, line, mtr, &err); @@ -1651,7 +1646,7 @@ fil_crypt_get_page_throttle_func( state->crypt_stat.pages_read_from_disk++; uintmax_t start = ut_time_us(NULL); - block = buf_page_get_gen(page_id, page_size, + block = buf_page_get_gen(page_id, zip_size, RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, file, line, mtr, &err); @@ -2020,7 +2015,7 @@ fil_crypt_flush_space( dberr_t err; if (buf_block_t* block = buf_page_get_gen( - page_id_t(space->id, 0), page_size_t(space->flags), + page_id_t(space->id, 0), space->zip_size(), RW_X_LATCH, NULL, BUF_GET, __FILE__, __LINE__, &mtr, &err)) { mtr.set_named_space(space); @@ -2527,10 +2522,9 @@ calculated checksum as if it does page could be valid unencrypted, encrypted, or corrupted. @param[in,out] page page frame (checksum is temporarily modified) -@param[in] page_size page size -@return whether the encrypted page is OK */ -bool -fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size) +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@return true if page is encrypted AND OK, false otherwise */ +bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size) { ut_ad(mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION)); @@ -2551,10 +2545,9 @@ fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size) switch (srv_checksum_algorithm_t(srv_checksum_algorithm)) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: - if (page_size.is_compressed()) { + if (zip_size) { return checksum == page_zip_calc_checksum( - page, page_size.physical(), - SRV_CHECKSUM_ALGORITHM_CRC32); + page, zip_size, SRV_CHECKSUM_ALGORITHM_CRC32); } return checksum == buf_calc_page_crc32(page); @@ -2575,12 +2568,12 @@ fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size) if (checksum == BUF_NO_CHECKSUM_MAGIC) { return true; } - if (page_size.is_compressed()) { + if (zip_size) { return checksum == page_zip_calc_checksum( - page, page_size.physical(), + page, zip_size, SRV_CHECKSUM_ALGORITHM_CRC32) || checksum == page_zip_calc_checksum( - page, page_size.physical(), + page, zip_size, SRV_CHECKSUM_ALGORITHM_INNODB); } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index e891c5bcdf8..0a35e183e06 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -261,7 +261,7 @@ fil_node_complete_io(fil_node_t* node, const IORequest& type); blocks at the end of file are ignored: they are not taken into account when calculating the byte offset within a space. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] byte_offset remainder of offset in bytes; in aio this must be divisible by the OS block size @param[in] len how many bytes to read; this must not cross a @@ -274,12 +274,12 @@ UNIV_INLINE dberr_t fil_read( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint byte_offset, ulint len, void* buf) { - return(fil_io(IORequestRead, true, page_id, page_size, + return(fil_io(IORequestRead, true, page_id, zip_size, byte_offset, len, buf, NULL)); } @@ -287,7 +287,7 @@ fil_read( blocks at the end of file are ignored: they are not taken into account when calculating the byte offset within a space. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] byte_offset remainder of offset in bytes; in aio this must be divisible by the OS block size @param[in] len how many bytes to write; this must not cross @@ -300,14 +300,14 @@ UNIV_INLINE dberr_t fil_write( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint byte_offset, ulint len, void* buf) { ut_ad(!srv_read_only_mode); - return(fil_io(IORequestWrite, true, page_id, page_size, + return(fil_io(IORequestWrite, true, page_id, zip_size, byte_offset, len, buf, NULL)); } @@ -389,8 +389,7 @@ void fil_space_t::set_imported() const fil_node_t* node = UT_LIST_GET_FIRST(chain); atomic_write_supported = node->atomic_write && srv_use_atomic_writes - && my_test_if_atomic_write(node->handle, - int(page_size_t(flags).physical())); + && my_test_if_atomic_write(node->handle, physical_size()); purpose = FIL_TYPE_TABLESPACE; } @@ -477,8 +476,7 @@ bool fil_node_t::read_page0(bool first) { ut_ad(mutex_own(&fil_system.mutex)); ut_a(space->purpose != FIL_TYPE_LOG); - const page_size_t page_size(space->flags); - const ulint psize = page_size.physical(); + const ulint psize = space->physical_size(); os_offset_t size_bytes = os_file_get_size(handle); ut_a(size_bytes != (os_offset_t) -1); @@ -507,12 +505,6 @@ bool fil_node_t::read_page0(bool first) const ulint free_limit = fsp_header_get_field(page, FSP_FREE_LIMIT); const ulint free_len = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE + page); - /* Try to read crypt_data from page 0 if it is not yet read. */ - if (!space->crypt_data) { - space->crypt_data = fil_space_read_crypt_data(page_size, page); - } - ut_free(buf2); - if (!fsp_flags_is_valid(flags, space->id)) { ulint cflags = fsp_flags_convert_from_101(flags); if (cflags == ULINT_UNDEFINED @@ -522,12 +514,20 @@ bool fil_node_t::read_page0(bool first) << ib::hex(space->flags) << " but found " << ib::hex(flags) << " in the file " << name; + ut_free(buf2); return false; } flags = cflags; } + /* Try to read crypt_data from page 0 if it is not yet read. */ + if (!space->crypt_data) { + space->crypt_data = fil_space_read_crypt_data( + fil_space_t::zip_size(flags), page); + } + ut_free(buf2); + if (UNIV_UNLIKELY(space_id != space->id)) { ib::error() << "Expected tablespace id " << space->id << " but found " << space_id @@ -647,9 +647,7 @@ retry: || (node->atomic_write && srv_use_atomic_writes && my_test_if_atomic_write( - node->handle, - int(page_size_t(space->flags) - .physical()))); + node->handle, space->physical_size())); } ut_a(success); @@ -921,8 +919,7 @@ fil_space_extend_must_retry( node->handle, node->name); } - const page_size_t pageSize(space->flags); - const ulint page_size = pageSize.physical(); + const ulint page_size = space->physical_size(); /* fil_read_first_page() expects srv_page_size bytes. fil_node_open_file() expects at least 4 * srv_page_size bytes.*/ @@ -982,7 +979,6 @@ fil_space_extend_must_retry( srv_tmp_space.set_last_file_size(pages_in_MiB); return(false); } - } /*******************************************************************//** @@ -1637,28 +1633,6 @@ void fil_space_t::close() mutex_exit(&fil_system.mutex); } -/** Returns the page size of the space and whether it is compressed or not. -The tablespace must be cached in the memory cache. -@param[in] id space id -@param[out] found true if tablespace was found -@return page size */ -const page_size_t -fil_space_get_page_size( - ulint id, - bool* found) -{ - const ulint flags = fil_space_get_flags(id); - - if (flags == ULINT_UNDEFINED) { - *found = false; - return(univ_page_size); - } - - *found = true; - - return(page_size_t(flags)); -} - void fil_system_t::create(ulint hash_size) { ut_ad(this == &fil_system); @@ -1896,13 +1870,11 @@ fil_write_flushed_lsn( const page_id_t page_id(TRX_SYS_SPACE, 0); - err = fil_read(page_id, univ_page_size, 0, srv_page_size, - buf); + err = fil_read(page_id, 0, 0, srv_page_size, buf); if (err == DB_SUCCESS) { mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, lsn); - err = fil_write(page_id, univ_page_size, 0, - srv_page_size, buf); + err = fil_write(page_id, 0, 0, srv_page_size, buf); fil_flush_file_spaces(FIL_TYPE_TABLESPACE); } @@ -3050,18 +3022,9 @@ err_exit: fsp_header_init_fields(page, space_id, flags); mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id); - const page_size_t page_size(flags); - IORequest request(IORequest::WRITE); - - if (!page_size.is_compressed()) { - - buf_flush_init_for_writing(NULL, page, NULL, 0); - - *err = os_file_write( - request, path, file, page, 0, page_size.physical()); - } else { + if (ulint zip_size = fil_space_t::zip_size(flags)) { page_zip_des_t page_zip; - page_zip_set_size(&page_zip, page_size.physical()); + page_zip_set_size(&page_zip, zip_size); page_zip.data = page + srv_page_size; #ifdef UNIV_DEBUG page_zip.m_start = @@ -3072,8 +3035,12 @@ err_exit: buf_flush_init_for_writing(NULL, page, &page_zip, 0); *err = os_file_write( - request, path, file, page_zip.data, 0, - page_size.physical()); + IORequestWrite, path, file, page_zip.data, 0, zip_size); + } else { + buf_flush_init_for_writing(NULL, page, NULL, 0); + + *err = os_file_write( + IORequestWrite, path, file, page, 0, srv_page_size); } ut_free(buf2); @@ -3487,7 +3454,8 @@ skip_validate: df_remote.get_first_page(); fil_space_crypt_t* crypt_data = first_page - ? fil_space_read_crypt_data(page_size_t(flags), first_page) + ? fil_space_read_crypt_data(fil_space_t::zip_size(flags), + first_page) : NULL; fil_space_t* space = fil_space_create( @@ -3835,7 +3803,8 @@ fil_ibd_load( const byte* first_page = file.get_first_page(); fil_space_crypt_t* crypt_data = first_page - ? fil_space_read_crypt_data(page_size_t(flags), first_page) + ? fil_space_read_crypt_data(fil_space_t::zip_size(flags), + first_page) : NULL; space = fil_space_create( file.name(), space_id, flags, FIL_TYPE_TABLESPACE, crypt_data); @@ -3909,7 +3878,7 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags) mtr_t mtr; mtr.start(); if (buf_block_t* b = buf_page_get( - page_id_t(space->id, 0), page_size_t(flags), + page_id_t(space->id, 0), space->zip_size(), RW_X_LATCH, &mtr)) { ulint f = fsp_header_get_flags(b->frame); /* Suppress the message if only the DATA_DIR flag to differs. */ @@ -4110,7 +4079,7 @@ fil_report_invalid_page_access( @param[in,out] type IO context @param[in] sync true if synchronous aio is desired @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] byte_offset remainder of offset in bytes; in aio this must be divisible by the OS block size @param[in] len how many bytes to read or write; this must @@ -4129,7 +4098,7 @@ fil_io( const IORequest& type, bool sync, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint byte_offset, ulint len, void* buf, @@ -4143,7 +4112,7 @@ fil_io( ut_ad(len > 0); ut_ad(byte_offset < srv_page_size); - ut_ad(!page_size.is_compressed() || byte_offset == 0); + ut_ad(!zip_size || byte_offset == 0); ut_ad(srv_page_size == 1UL << srv_page_size_shift); compile_time_assert((1U << UNIV_PAGE_SIZE_SHIFT_MAX) == UNIV_PAGE_SIZE_MAX); @@ -4154,7 +4123,7 @@ fil_io( /* ibuf bitmap pages must be read in the sync AIO mode: */ ut_ad(recv_no_ibuf_operations || req_type.is_write() - || !ibuf_bitmap_page(page_id, page_size) + || !ibuf_bitmap_page(page_id, zip_size) || sync || req_type.is_log()); @@ -4170,7 +4139,7 @@ fil_io( } else if (req_type.is_read() && !recv_no_ibuf_operations - && ibuf_page(page_id, page_size, NULL)) { + && ibuf_page(page_id, zip_size, NULL)) { mode = OS_AIO_IBUF; @@ -4312,37 +4281,10 @@ fil_io( /* Now we have made the changes in the data structures of fil_system */ mutex_exit(&fil_system.mutex); - /* Calculate the low 32 bits and the high 32 bits of the file offset */ + if (!zip_size) zip_size = srv_page_size; - if (!page_size.is_compressed()) { - - offset = ((os_offset_t) cur_page_no - << srv_page_size_shift) + byte_offset; - - ut_a(node->size - cur_page_no - >= ((byte_offset + len + (srv_page_size - 1)) - >> srv_page_size_shift)); - } else { - ulint size_shift; - - switch (page_size.physical()) { - case 1024: size_shift = 10; break; - case 2048: size_shift = 11; break; - case 4096: size_shift = 12; break; - case 8192: size_shift = 13; break; - case 16384: size_shift = 14; break; - case 32768: size_shift = 15; break; - case 65536: size_shift = 16; break; - default: ut_error; - } - - offset = ((os_offset_t) cur_page_no << size_shift) - + byte_offset; - - ut_a(node->size - cur_page_no - >= (len + (page_size.physical() - 1)) - / page_size.physical()); - } + offset = os_offset_t(cur_page_no) * zip_size + byte_offset; + ut_ad(node->size - cur_page_no >= (len + (zip_size - 1)) / zip_size); /* Do AIO */ diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc index 57bb736d230..adb41709027 100644 --- a/storage/innobase/fil/fil0pagecompress.cc +++ b/storage/innobase/fil/fil0pagecompress.cc @@ -250,8 +250,7 @@ success: page_t page[UNIV_PAGE_SIZE_MAX]; memcpy(page, out_buf, srv_page_size); ut_ad(fil_page_decompress(tmp_buf, page)); - ut_ad(!buf_page_is_corrupted(false, page, univ_page_size, - NULL)); + ut_ad(!buf_page_is_corrupted(false, page, 0, NULL)); } #endif /* UNIV_DEBUG */ diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 3070f989c04..fdcb4070894 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -356,8 +356,14 @@ Datafile::read_first_page(bool read_only_mode) } } - const page_size_t ps(m_flags); - if (ps.physical() > page_size) { + ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(m_flags); + if (!ssize) ssize = UNIV_PAGE_SSIZE_ORIG; + const ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(m_flags); + const size_t logical_size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize); + const size_t physical_size = zip_ssize + ? (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize : logical_size; + + if (physical_size > page_size) { ib::error() << "File " << m_filepath << " should be longer than " << page_size << " bytes"; @@ -543,13 +549,13 @@ err_exit: goto err_exit; } - const page_size_t page_size(m_flags); + ulint logical_size = fil_space_t::logical_size(m_flags); - if (srv_page_size != page_size.logical()) { + if (srv_page_size != logical_size) { /* Logical size must be innodb_page_size. */ ib::error() << "Data file '" << m_filepath << "' uses page size " - << page_size.logical() << ", but the innodb_page_size" + << logical_size << ", but the innodb_page_size" " start-up parameter is " << srv_page_size; free_first_page(); @@ -568,7 +574,8 @@ err_exit: goto err_exit; } - if (buf_page_is_corrupted(false, m_first_page, page_size)) { + if (buf_page_is_corrupted(false, m_first_page, + fil_space_t::zip_size(m_flags))) { /* Look for checksum and other corruptions. */ error_txt = "Checksum mismatch"; goto err_exit; @@ -630,7 +637,6 @@ Datafile::find_space_id() for (ulint page_size = UNIV_ZIP_SIZE_MIN; page_size <= UNIV_PAGE_SIZE_MAX; page_size <<= 1) { - /* map[space_id] = count of pages */ typedef std::map< ulint, @@ -681,27 +687,16 @@ Datafile::find_space_id() equal to srv_page_size. */ if (page_size == srv_page_size) { noncompressed_ok = !buf_page_is_corrupted( - false, page, univ_page_size, NULL); + false, page, 0, NULL); } bool compressed_ok = false; - /* file-per-table tablespaces can be compressed with - the same physical and logical page size. General - tablespaces must have different physical and logical - page sizes in order to be compressed. For this check, - assume the page is compressed if univ_page_size. - logical() is equal to or less than 16k and the - page_size we are checking is equal to or less than - srv_page_size. */ if (srv_page_size <= UNIV_PAGE_SIZE_DEF && page_size <= srv_page_size) { - const page_size_t compr_page_size( - page_size, srv_page_size, - true); - compressed_ok = !buf_page_is_corrupted( - false, page, compr_page_size, NULL); + false, page, + page_size, NULL); } if (noncompressed_ok || compressed_ok) { @@ -801,21 +796,21 @@ Datafile::restore_from_doublewrite() /* The flags on the page should be converted later. */ } - const page_size_t page_size(flags); + ulint physical_size = fil_space_t::physical_size(flags); ut_a(page_get_page_no(page) == page_id.page_no()); ib::info() << "Restoring page " << page_id << " of datafile '" << m_filepath << "' from the doublewrite buffer. Writing " - << page_size.physical() << " bytes into file '" + << physical_size << " bytes into file '" << m_filepath << "'"; IORequest request(IORequest::WRITE); return(os_file_write( request, - m_filepath, m_handle, page, 0, page_size.physical()) + m_filepath, m_handle, page, 0, physical_size) != DB_SUCCESS); } diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 9e92646556c..2aed55db256 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -50,7 +50,6 @@ typedef ulint page_no_t; /** Return an extent to the free list of a space. @param[in,out] space tablespace @param[in] offset page number in the extent -@param[in] page_size page size @param[in,out] mtr mini-transaction */ MY_ATTRIBUTE((nonnull)) static @@ -58,7 +57,6 @@ void fsp_free_extent( fil_space_t* space, page_no_t offset, - const page_size_t& page_size, mtr_t* mtr); /********************************************************************//** @@ -78,7 +76,6 @@ We think of the extent lists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL -> FSEG_FREE. @param[in] inode segment inode @param[in] space tablespace -@param[in] page_size page size @param[in,out] mtr mini-transaction @return the first extent descriptor, or NULL if none */ MY_ATTRIBUTE((nonnull, warn_unused_result)) @@ -87,7 +84,6 @@ xdes_t* fseg_get_first_extent( fseg_inode_t* inode, const fil_space_t* space, - const page_size_t& page_size, mtr_t* mtr); /** Put new extents to the free list if there are free extents above the free @@ -111,7 +107,6 @@ fsp_fill_free_list( This function implements the intelligent allocation strategy which tries to minimize file space fragmentation. @param[in,out] space tablespace -@param[in] page_size page size @param[in,out] seg_inode segment inode @param[in] hint hint of which page would be desirable @param[in] direction if the new page is needed because of @@ -132,7 +127,6 @@ static buf_block_t* fseg_alloc_free_page_low( fil_space_t* space, - const page_size_t& page_size, fseg_inode_t* seg_inode, ulint hint, byte direction, @@ -147,24 +141,16 @@ fseg_alloc_free_page_low( /** Gets a pointer to the space header and x-locks its page. @param[in] space tablespace -@param[in] page_size page size @param[in,out] mtr mini-transaction @return pointer to the space header, page x-locked */ -UNIV_INLINE -fsp_header_t* -fsp_get_space_header( - const fil_space_t* space, - const page_size_t& page_size, - mtr_t* mtr) +inline fsp_header_t* fsp_get_space_header(const fil_space_t* space, mtr_t* mtr) { buf_block_t* block; fsp_header_t* header; ut_ad(space->purpose != FIL_TYPE_LOG); - ut_ad(!FSP_FLAGS_GET_ZIP_SSIZE(space->flags) - == !page_size.is_compressed()); - block = buf_page_get(page_id_t(space->id, 0), page_size, + block = buf_page_get(page_id_t(space->id, 0), space->zip_size(), RW_SX_LATCH, mtr); header = FSP_HEADER_OFFSET + buf_block_get_frame(block); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -427,9 +413,9 @@ xdes_get_descriptor_with_space_hdr( return(NULL); } - const page_size_t page_size(space->flags); + const ulint zip_size = space->zip_size(); - descr_page_no = xdes_calc_descriptor_page(page_size, offset); + descr_page_no = xdes_calc_descriptor_page(zip_size, offset); buf_block_t* block; @@ -440,7 +426,7 @@ xdes_get_descriptor_with_space_hdr( block = NULL; } else { block = buf_page_get( - page_id_t(space->id, descr_page_no), page_size, + page_id_t(space->id, descr_page_no), zip_size, RW_SX_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -453,7 +439,7 @@ xdes_get_descriptor_with_space_hdr( } return(descr_page + XDES_ARR_OFFSET - + XDES_SIZE * xdes_calc_descriptor_index(page_size, offset)); + + XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset)); } /** Get the extent descriptor of a page. @@ -465,22 +451,17 @@ defined, as they are uninitialized above the free limit. @param[in] space tablespace @param[in] offset page offset; if equal to the free limit, we try to add new extents to the space free list -@param[in] page_size page size @param[in,out] mtr mini-transaction @return the extent descriptor */ MY_ATTRIBUTE((warn_unused_result)) static xdes_t* -xdes_get_descriptor( - const fil_space_t* space, - page_no_t offset, - const page_size_t& page_size, - mtr_t* mtr) +xdes_get_descriptor(const fil_space_t* space, page_no_t offset, mtr_t* mtr) { buf_block_t* block; fsp_header_t* sp_header; - block = buf_page_get(page_id_t(space->id, 0), page_size, + block = buf_page_get(page_id_t(space->id, 0), space->zip_size(), RW_SX_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -499,7 +480,6 @@ defined, as they are uninitialized above the free limit. @param[in] space tablespace @param[in] page descriptor page offset @param[in] offset page offset -@param[in] page_size page size @param[in,out] mtr mini-transaction @return the extent descriptor @retval NULL if the descriptor is not available */ @@ -510,15 +490,16 @@ xdes_get_descriptor_const( const fil_space_t* space, page_no_t page, page_no_t offset, - const page_size_t& page_size, mtr_t* mtr) { ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_S_LOCK)); ut_ad(offset < space->free_limit); ut_ad(offset < space->size_in_header); + const ulint zip_size = space->zip_size(); + if (buf_block_t* block = buf_page_get(page_id_t(space->id, page), - page_size, RW_S_LATCH, mtr)) { + zip_size, RW_S_LATCH, mtr)) { buf_block_dbg_add_level(block, SYNC_FSP_PAGE); ut_ad(page != 0 || space->free_limit == mach_read_from_4( @@ -529,7 +510,7 @@ xdes_get_descriptor_const( + block->frame)); return(block->frame + XDES_ARR_OFFSET + XDES_SIZE - * xdes_calc_descriptor_index(page_size, offset)); + * xdes_calc_descriptor_index(zip_size, offset)); } return(NULL); @@ -538,7 +519,6 @@ xdes_get_descriptor_const( /** Get a pointer to the extent descriptor. The page where the extent descriptor resides is x-locked. @param[in] space tablespace -@param[in] page_size page size @param[in] lst_node file address of the list node contained in the descriptor @param[in,out] mtr mini-transaction @@ -548,14 +528,13 @@ UNIV_INLINE xdes_t* xdes_lst_get_descriptor( const fil_space_t* space, - const page_size_t& page_size, fil_addr_t lst_node, mtr_t* mtr) { ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); - ut_ad(page_size.equals_to(page_size_t(space->flags))); - return(fut_get_ptr(space->id, page_size, lst_node, RW_SX_LATCH, mtr) - - XDES_FLST_NODE); + return fut_get_ptr(space->id, space->zip_size(), + lst_node, RW_SX_LATCH, mtr) + - XDES_FLST_NODE; } /********************************************************************//** @@ -706,12 +685,12 @@ fsp_header_init_fields( @param[in,out] mtr mini-transaction */ void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr) { - const page_id_t page_id(space->id, 0); - const page_size_t page_size(space->flags); + const page_id_t page_id(space->id, 0); + const ulint zip_size = space->zip_size(); mtr_x_lock(&space->latch, mtr); - buf_block_t* block = buf_page_create(page_id, page_size, mtr); - buf_page_get(page_id, page_size, RW_SX_LATCH, mtr); + buf_block_t* block = buf_page_create(page_id, zip_size, mtr); + buf_page_get(page_id, zip_size, RW_SX_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); space->size_in_header = size; @@ -820,6 +799,44 @@ fsp_try_extend_data_file_with_pages( return(success); } +/** Calculate the number of physical pages in an extent for this file. +@param[in] physical_size page_size of the datafile +@return number of pages in an extent for this file */ +inline ulint fsp_get_extent_size_in_pages(ulint physical_size) +{ + return (FSP_EXTENT_SIZE << srv_page_size_shift) / physical_size; +} + + +/** Calculate the number of pages to extend a datafile. +We extend single-table tablespaces first one extent at a time, +but 4 at a time for bigger tablespaces. It is not enough to extend always +by one extent, because we need to add at least one extent to FSP_FREE. +A single extent descriptor page will track many extents. And the extent +that uses its extent descriptor page is put onto the FSP_FREE_FRAG list. +Extents that do not use their extent descriptor page are added to FSP_FREE. +The physical page size is used to determine how many extents are tracked +on one extent descriptor page. See xdes_calc_descriptor_page(). +@param[in] physical_size page size in data file +@param[in] size current number of pages in the datafile +@return number of pages to extend the file. */ +static ulint fsp_get_pages_to_extend_ibd(ulint physical_size, ulint size) +{ + ulint extent_size = fsp_get_extent_size_in_pages(physical_size); + /* The threshold is set at 32MiB except when the physical page + size is small enough that it must be done sooner. */ + ulint threshold = std::min(32 * extent_size, physical_size); + + if (size >= threshold) { + /* Below in fsp_fill_free_list() we assume + that we add at most FSP_FREE_ADD extents at + a time */ + extent_size *= FSP_FREE_ADD; + } + + return extent_size; +} + /** Try to extend the last data file of a tablespace if it is auto-extending. @param[in,out] space tablespace @param[in,out] header tablespace header @@ -872,8 +889,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr) size = mach_read_from_4(header + FSP_SIZE); ut_ad(size == space->size_in_header); - const page_size_t page_size( - mach_read_from_4(header + FSP_SPACE_FLAGS)); + const ulint ps = space->physical_size(); switch (space->id) { case TRX_SYS_SPACE: @@ -883,8 +899,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr) size_increase = srv_tmp_space.get_increment(); break; default: - ulint extent_pages - = fsp_get_extent_size_in_pages(page_size); + ulint extent_pages = fsp_get_extent_size_in_pages(ps); if (size < extent_pages) { /* Let us first extend the file to extent_size */ if (!fsp_try_extend_data_file_with_pages( @@ -895,7 +910,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr) size = extent_pages; } - size_increase = fsp_get_pages_to_extend_ibd(page_size, size); + size_increase = fsp_get_pages_to_extend_ibd(ps, size); } if (size_increase == 0) { @@ -910,7 +925,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr) to the space header */ space->size_in_header = ut_calc_align_down( - space->size, (1024 * 1024) / page_size.physical()); + space->size, (1024 * 1024) / ps); mlog_write_ulint( header + FSP_SIZE, space->size_in_header, MLOG_4BYTES, mtr); @@ -918,47 +933,6 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr) return(size_increase); } -/** Calculate the number of pages to extend a datafile. -We extend single-table tablespaces first one extent at a time, -but 4 at a time for bigger tablespaces. It is not enough to extend always -by one extent, because we need to add at least one extent to FSP_FREE. -A single extent descriptor page will track many extents. And the extent -that uses its extent descriptor page is put onto the FSP_FREE_FRAG list. -Extents that do not use their extent descriptor page are added to FSP_FREE. -The physical page size is used to determine how many extents are tracked -on one extent descriptor page. See xdes_calc_descriptor_page(). -@param[in] page_size page_size of the datafile -@param[in] size current number of pages in the datafile -@return number of pages to extend the file. */ -ulint -fsp_get_pages_to_extend_ibd( - const page_size_t& page_size, - ulint size) -{ - ulint size_increase; /* number of pages to extend this file */ - ulint extent_size; /* one megabyte, in pages */ - ulint threshold; /* The size of the tablespace (in number - of pages) where we start allocating more - than one extent at a time. */ - - extent_size = fsp_get_extent_size_in_pages(page_size); - - /* The threshold is set at 32MiB except when the physical page - size is small enough that it must be done sooner. */ - threshold = ut_min(32 * extent_size, page_size.physical()); - - if (size < threshold) { - size_increase = extent_size; - } else { - /* Below in fsp_fill_free_list() we assume - that we add at most FSP_FREE_ADD extents at - a time */ - size_increase = FSP_FREE_ADD * extent_size; - } - - return(size_increase); -} - /** Reset the page type. Data files created before MySQL 5.1.48 may contain garbage in FIL_PAGE_TYPE. In MySQL 3.23.53, only undo log pages and index pages were tagged. @@ -1009,7 +983,7 @@ fsp_fill_free_list( ut_ad(size == space->size_in_header); ut_ad(limit == space->free_limit); - const page_size_t page_size(space->flags); + const ulint zip_size = space->zip_size(); if (size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) { bool skip_resize = init_space; @@ -1034,7 +1008,7 @@ fsp_fill_free_list( || ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) { bool init_xdes - = (ut_2pow_remainder(i, page_size.physical()) == 0); + = (ut_2pow_remainder(i, space->physical_size()) == 0); space->free_limit = i + FSP_EXTENT_SIZE; mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE, @@ -1052,10 +1026,10 @@ fsp_fill_free_list( const page_id_t page_id(space->id, i); block = buf_page_create( - page_id, page_size, mtr); + page_id, zip_size, mtr); buf_page_get( - page_id, page_size, RW_SX_LATCH, mtr); + page_id, zip_size, RW_SX_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -1082,10 +1056,10 @@ fsp_fill_free_list( i + FSP_IBUF_BITMAP_OFFSET); block = buf_page_create( - page_id, page_size, &ibuf_mtr); + page_id, zip_size, &ibuf_mtr); buf_page_get( - page_id, page_size, RW_SX_LATCH, + page_id, zip_size, RW_SX_LATCH, &ibuf_mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); @@ -1138,7 +1112,6 @@ fsp_fill_free_list( /** Allocates a new free extent. @param[in,out] space tablespace -@param[in] page_size page size @param[in] hint hint of which extent would be desirable: any page offset in the extent goes; the hint must not be > FSP_FREE_LIMIT @param[in,out] mtr mini-transaction @@ -1147,7 +1120,6 @@ static xdes_t* fsp_alloc_free_extent( fil_space_t* space, - const page_size_t& page_size, ulint hint, mtr_t* mtr) { @@ -1156,7 +1128,7 @@ fsp_alloc_free_extent( xdes_t* descr; buf_block_t* desc_block = NULL; - header = fsp_get_space_header(space, page_size, mtr); + header = fsp_get_space_header(space, mtr); descr = xdes_get_descriptor_with_space_hdr( header, space, hint, mtr, false, &desc_block); @@ -1182,8 +1154,7 @@ fsp_alloc_free_extent( return(NULL); /* No free extents left */ } - descr = xdes_lst_get_descriptor( - space, page_size, first, mtr); + descr = xdes_lst_get_descriptor(space, first, mtr); } flst_remove(header + FSP_FREE, descr + XDES_FLST_NODE, mtr); @@ -1234,7 +1205,6 @@ not previously x-latched. It is assumed that the block has been x-latched only by mtr, and freed in mtr in that case. @param[in,out] space tablespace @param[in] offset page number of the allocated page -@param[in] page_size page size of the allocated page @param[in] rw_latch RW_SX_LATCH, RW_X_LATCH @param[in,out] mtr mini-transaction of the allocation @param[in,out] init_mtr mini-transaction for initializing the page @@ -1245,15 +1215,12 @@ buf_block_t* fsp_page_create( fil_space_t* space, page_no_t offset, - const page_size_t& page_size, rw_lock_type_t rw_latch, mtr_t* mtr, mtr_t* init_mtr) { - ut_ad(page_size.equals_to(page_size_t(space->flags))); - buf_block_t* block = buf_page_create(page_id_t(space->id, offset), - page_size, init_mtr); + space->zip_size(), init_mtr); ut_d(bool latched = mtr_memo_contains_flagged(mtr, block, MTR_MEMO_PAGE_X_FIX @@ -1293,7 +1260,6 @@ fsp_page_create( /** Allocates a single free page from a space. The page is marked as used. @param[in,out] space tablespace -@param[in] page_size page size @param[in] hint hint of which page would be desirable @param[in] rw_latch RW_SX_LATCH, RW_X_LATCH @param[in,out] mtr mini-transaction @@ -1307,7 +1273,6 @@ static MY_ATTRIBUTE((warn_unused_result, nonnull)) buf_block_t* fsp_alloc_free_page( fil_space_t* space, - const page_size_t& page_size, ulint hint, rw_lock_type_t rw_latch, mtr_t* mtr, @@ -1320,7 +1285,7 @@ fsp_alloc_free_page( const ulint space_id = space->id; ut_d(fsp_space_modify_check(space, mtr)); - header = fsp_get_space_header(space, page_size, mtr); + header = fsp_get_space_header(space, mtr); /* Get the hinted descriptor */ descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr); @@ -1339,8 +1304,7 @@ fsp_alloc_free_page( FREE_FRAG list. But we will allocate our page from the the free extent anyway. */ - descr = fsp_alloc_free_extent(space, page_size, - hint, mtr); + descr = fsp_alloc_free_extent(space, hint, mtr); if (descr == NULL) { /* No free space left */ @@ -1352,8 +1316,7 @@ fsp_alloc_free_page( flst_add_last(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, mtr); } else { - descr = xdes_lst_get_descriptor(space, page_size, - first, mtr); + descr = xdes_lst_get_descriptor(space, first, mtr); } /* Reset the hint */ @@ -1401,23 +1364,15 @@ fsp_alloc_free_page( } fsp_alloc_from_free_frag(header, descr, free, mtr); - return(fsp_page_create(space, page_no, page_size, rw_latch, - mtr, init_mtr)); + return fsp_page_create(space, page_no, rw_latch, mtr, init_mtr); } /** Frees a single page of a space. The page is marked as free and clean. @param[in,out] space tablespace -@param[in] page_id page id -@param[in] page_size page size +@param[in] offset page number @param[in,out] mtr mini-transaction */ -static -void -fsp_free_page( - fil_space_t* space, - ulint offset, - const page_size_t& page_size, - mtr_t* mtr) +static void fsp_free_page(fil_space_t* space, page_no_t offset, mtr_t* mtr) { fsp_header_t* header; xdes_t* descr; @@ -1429,7 +1384,7 @@ fsp_free_page( /* fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */ - header = fsp_get_space_header(space, page_size, mtr); + header = fsp_get_space_header(space, mtr); descr = xdes_get_descriptor_with_space_hdr( header, space, offset, mtr); @@ -1498,29 +1453,22 @@ fsp_free_page( /* The extent has become free: move it to another list */ flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE, mtr); - fsp_free_extent(space, offset, page_size, mtr); + fsp_free_extent(space, offset, mtr); } } /** Return an extent to the free list of a space. @param[in,out] space tablespace @param[in] offset page number in the extent -@param[in] page_size page size @param[in,out] mtr mini-transaction */ -static -void -fsp_free_extent( - fil_space_t* space, - page_no_t offset, - const page_size_t& page_size, - mtr_t* mtr) +static void fsp_free_extent(fil_space_t* space, page_no_t offset, mtr_t* mtr) { fsp_header_t* header; xdes_t* descr; ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); - header = fsp_get_space_header(space, page_size, mtr); + header = fsp_get_space_header(space, mtr); descr = xdes_get_descriptor_with_space_hdr( header, space, offset, mtr); @@ -1533,10 +1481,16 @@ fsp_free_extent( space->free_len++; } +/** @return Number of segment inodes which fit on a single page */ +inline ulint FSP_SEG_INODES_PER_PAGE(ulint physical_size) +{ + return (physical_size - FSEG_ARR_OFFSET - 10) / FSEG_INODE_SIZE; +} + /** Returns the nth inode slot on an inode page. @param[in] page segment inode page @param[in] i inode index on page -@param[in] page_size page size +@param[in] physical_size page size @param[in,out] mtr mini-transaction @return segment inode */ UNIV_INLINE @@ -1544,10 +1498,10 @@ fseg_inode_t* fsp_seg_inode_page_get_nth_inode( page_t* page, ulint i, - const page_size_t& page_size, + ulint physical_size, mtr_t* mtr) { - ut_ad(i < FSP_SEG_INODES_PER_PAGE(page_size)); + ut_ad(i < FSP_SEG_INODES_PER_PAGE(physical_size)); ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_SX_FIX)); return(page + FSEG_ARR_OFFSET + FSEG_INODE_SIZE * i); @@ -1555,23 +1509,23 @@ fsp_seg_inode_page_get_nth_inode( /** Looks for a used segment inode on a segment inode page. @param[in] page segment inode page -@param[in] page_size page size +@param[in] physical_size page size @param[in,out] mtr mini-transaction @return segment inode index, or ULINT_UNDEFINED if not found */ static ulint fsp_seg_inode_page_find_used( page_t* page, - const page_size_t& page_size, + ulint physical_size, mtr_t* mtr) { ulint i; fseg_inode_t* inode; - for (i = 0; i < FSP_SEG_INODES_PER_PAGE(page_size); i++) { + for (i = 0; i < FSP_SEG_INODES_PER_PAGE(physical_size); i++) { inode = fsp_seg_inode_page_get_nth_inode( - page, i, page_size, mtr); + page, i, physical_size, mtr); if (mach_read_from_8(inode + FSEG_ID)) { /* This is used */ @@ -1588,7 +1542,7 @@ fsp_seg_inode_page_find_used( /** Looks for an unused segment inode on a segment inode page. @param[in] page segment inode page @param[in] i search forward starting from this index -@param[in] page_size page size +@param[in] physical_size page size @param[in,out] mtr mini-transaction @return segment inode index, or ULINT_UNDEFINED if not found */ static @@ -1596,15 +1550,15 @@ ulint fsp_seg_inode_page_find_free( page_t* page, ulint i, - const page_size_t& page_size, + ulint physical_size, mtr_t* mtr) { - for (; i < FSP_SEG_INODES_PER_PAGE(page_size); i++) { + for (; i < FSP_SEG_INODES_PER_PAGE(physical_size); i++) { fseg_inode_t* inode; inode = fsp_seg_inode_page_get_nth_inode( - page, i, page_size, mtr); + page, i, physical_size, mtr); if (!mach_read_from_8(inode + FSEG_ID)) { /* This is unused */ @@ -1638,10 +1592,7 @@ fsp_alloc_seg_inode_page( ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET); ut_ad(page_get_space_id(page_align(space_header)) == space->id); - const page_size_t page_size(space->flags); - - block = fsp_alloc_free_page( - space, page_size, 0, RW_SX_LATCH, mtr, mtr); + block = fsp_alloc_free_page(space, 0, RW_SX_LATCH, mtr, mtr); if (block == NULL) { @@ -1656,10 +1607,12 @@ fsp_alloc_seg_inode_page( mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_INODE, MLOG_2BYTES, mtr); - for (ulint i = 0; i < FSP_SEG_INODES_PER_PAGE(page_size); i++) { + const ulint physical_size = space->physical_size(); + + for (ulint i = 0; i < FSP_SEG_INODES_PER_PAGE(physical_size); i++) { inode = fsp_seg_inode_page_get_nth_inode( - page, i, page_size, mtr); + page, i, physical_size, mtr); mlog_write_ull(inode + FSEG_ID, 0, mtr); } @@ -1697,25 +1650,27 @@ fsp_alloc_seg_inode( && !fsp_alloc_seg_inode_page(space, space_header, mtr)) { return(NULL); } - const page_size_t page_size(space->flags); const page_id_t page_id( space->id, flst_get_first(space_header + FSP_SEG_INODES_FREE, mtr).page); - block = buf_page_get(page_id, page_size, RW_SX_LATCH, mtr); + block = buf_page_get(page_id, space->zip_size(), RW_SX_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_FSP_PAGE); fil_block_check_type(*block, FIL_PAGE_INODE, mtr); page = buf_block_get_frame(block); - n = fsp_seg_inode_page_find_free(page, 0, page_size, mtr); + const ulint physical_size = space->physical_size(); + + n = fsp_seg_inode_page_find_free(page, 0, physical_size, mtr); ut_a(n != ULINT_UNDEFINED); - inode = fsp_seg_inode_page_get_nth_inode(page, n, page_size, mtr); + inode = fsp_seg_inode_page_get_nth_inode(page, n, physical_size, mtr); if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1, - page_size, mtr)) { + physical_size, + mtr)) { /* There are no other unused headers left on the page: move it to another list */ @@ -1733,14 +1688,10 @@ fsp_alloc_seg_inode( /** Frees a file segment inode. @param[in,out] space tablespace -@param[in] page_size page size @param[in,out] inode segment inode @param[in,out] mtr mini-transaction */ -static -void -fsp_free_seg_inode( +static void fsp_free_seg_inode( fil_space_t* space, - const page_size_t& page_size, fseg_inode_t* inode, mtr_t* mtr) { @@ -1751,12 +1702,14 @@ fsp_free_seg_inode( page = page_align(inode); - space_header = fsp_get_space_header(space, page_size, mtr); + space_header = fsp_get_space_header(space, mtr); ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); + const ulint physical_size = space->physical_size(); + if (ULINT_UNDEFINED - == fsp_seg_inode_page_find_free(page, 0, page_size, mtr)) { + == fsp_seg_inode_page_find_free(page, 0, physical_size, mtr)) { /* Move the page to another list */ @@ -1771,21 +1724,21 @@ fsp_free_seg_inode( mlog_write_ulint(inode + FSEG_MAGIC_N, 0xfa051ce3, MLOG_4BYTES, mtr); if (ULINT_UNDEFINED - == fsp_seg_inode_page_find_used(page, page_size, mtr)) { + == fsp_seg_inode_page_find_used(page, physical_size, mtr)) { /* There are no other used headers left on the page: free it */ flst_remove(space_header + FSP_SEG_INODES_FREE, page + FSEG_INODE_PAGE_NODE, mtr); - fsp_free_page(space, page_get_page_no(page), page_size, mtr); + fsp_free_page(space, page_get_page_no(page), mtr); } } /** Returns the file segment inode, page x-latched. @param[in] header segment header @param[in] space space id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] mtr mini-transaction @param[out] block inode block, or NULL to ignore @return segment inode, page x-latched; NULL if the inode is free */ @@ -1794,7 +1747,7 @@ fseg_inode_t* fseg_inode_try_get( fseg_header_t* header, ulint space, - const page_size_t& page_size, + ulint zip_size, mtr_t* mtr, buf_block_t** block) { @@ -1805,7 +1758,7 @@ fseg_inode_try_get( inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET); ut_ad(space == mach_read_from_4(header + FSEG_HDR_SPACE)); - inode = fut_get_ptr(space, page_size, inode_addr, RW_SX_LATCH, mtr, + inode = fut_get_ptr(space, zip_size, inode_addr, RW_SX_LATCH, mtr, block); if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) { @@ -1822,7 +1775,7 @@ fseg_inode_try_get( /** Returns the file segment inode, page x-latched. @param[in] header segment header @param[in] space space id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] mtr mini-transaction @param[out] block inode block @return segment inode, page x-latched */ @@ -1831,12 +1784,12 @@ fseg_inode_t* fseg_inode_get( fseg_header_t* header, ulint space, - const page_size_t& page_size, + ulint zip_size, mtr_t* mtr, buf_block_t** block = NULL) { fseg_inode_t* inode - = fseg_inode_try_get(header, space, page_size, mtr, block); + = fseg_inode_try_get(header, space, zip_size, mtr, block); ut_a(inode); return(inode); } @@ -1996,11 +1949,11 @@ fseg_create( <= srv_page_size - FIL_PAGE_DATA_END); mtr_x_lock(&space->latch, mtr); - const page_size_t page_size(space->flags); ut_d(fsp_space_modify_check(space, mtr)); if (page != 0) { - block = buf_page_get(page_id_t(space->id, page), page_size, + block = buf_page_get(page_id_t(space->id, page), + space->zip_size(), RW_SX_LATCH, mtr); header = byte_offset + buf_block_get_frame(block); @@ -2019,7 +1972,7 @@ fseg_create( DBUG_RETURN(NULL); } - space_header = fsp_get_space_header(space, page_size, mtr); + space_header = fsp_get_space_header(space, mtr); inode = fsp_alloc_seg_inode(space, space_header, mtr); @@ -2048,7 +2001,7 @@ fseg_create( } if (page == 0) { - block = fseg_alloc_free_page_low(space, page_size, + block = fseg_alloc_free_page_low(space, inode, 0, FSP_UP, RW_SX_LATCH, mtr, mtr #ifdef UNIV_DEBUG @@ -2061,9 +2014,7 @@ fseg_create( ut_ad(!has_done_reservation || block != NULL); if (block == NULL) { - - fsp_free_seg_inode(space, page_size, inode, mtr); - + fsp_free_seg_inode(space, inode, mtr); goto funct_exit; } @@ -2140,9 +2091,7 @@ fseg_n_reserved_pages( space_id = page_get_space_id(page_align(header)); space = mtr_x_lock_space(space_id, mtr); - const page_size_t page_size(space->flags); - - inode = fseg_inode_get(header, space_id, page_size, mtr); + inode = fseg_inode_get(header, space_id, space->zip_size(), mtr); ret = fseg_n_reserved_pages_low(inode, used, mtr); @@ -2155,7 +2104,6 @@ the free list is empty, and the extents can be allocated consecutively from the hint onward. @param[in] inode segment inode @param[in] space tablespace -@param[in] page_size page size @param[in] hint hint which extent would be good as the first extent @param[in,out] mtr mini-transaction */ @@ -2164,7 +2112,6 @@ void fseg_fill_free_list( fseg_inode_t* inode, fil_space_t* space, - const page_size_t& page_size, ulint hint, mtr_t* mtr) { @@ -2194,7 +2141,7 @@ fseg_fill_free_list( } for (i = 0; i < FSEG_FREE_LIST_MAX_LEN; i++) { - descr = xdes_get_descriptor(space, hint, page_size, mtr); + descr = xdes_get_descriptor(space, hint, mtr); if ((descr == NULL) || (XDES_FREE != xdes_get_state(descr, mtr))) { @@ -2204,7 +2151,7 @@ fseg_fill_free_list( return; } - descr = fsp_alloc_free_extent(space, page_size, hint, mtr); + descr = fsp_alloc_free_extent(space, hint, mtr); xdes_set_state(descr, XDES_FSEG, mtr); @@ -2224,7 +2171,6 @@ NOTE that the extent returned still resides in the segment free list, it is not yet taken off it! @param[in] inode segment inode @param[in,out] space tablespace -@param[in] page_size page size @param[in,out] mtr mini-transaction @retval NULL if no page could be allocated @retval block rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded @@ -2235,7 +2181,6 @@ xdes_t* fseg_alloc_free_extent( fseg_inode_t* inode, fil_space_t* space, - const page_size_t& page_size, mtr_t* mtr) { xdes_t* descr; @@ -2251,10 +2196,10 @@ fseg_alloc_free_extent( first = flst_get_first(inode + FSEG_FREE, mtr); - descr = xdes_lst_get_descriptor(space, page_size, first, mtr); + descr = xdes_lst_get_descriptor(space, first, mtr); } else { /* Segment free list was empty, allocate from space */ - descr = fsp_alloc_free_extent(space, page_size, 0, mtr); + descr = fsp_alloc_free_extent(space, 0, mtr); if (descr == NULL) { @@ -2268,7 +2213,7 @@ fseg_alloc_free_extent( flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr); /* Try to fill the segment free list */ - fseg_fill_free_list(inode, space, page_size, + fseg_fill_free_list(inode, space, xdes_get_offset(descr) + FSP_EXTENT_SIZE, mtr); } @@ -2280,7 +2225,6 @@ fseg_alloc_free_extent( This function implements the intelligent allocation strategy which tries to minimize file space fragmentation. @param[in,out] space tablespace -@param[in] page_size page size @param[in,out] seg_inode segment inode @param[in] hint hint of which page would be desirable @param[in] direction if the new page is needed because of @@ -2301,7 +2245,6 @@ static buf_block_t* fseg_alloc_free_page_low( fil_space_t* space, - const page_size_t& page_size, fseg_inode_t* seg_inode, ulint hint, byte direction, @@ -2336,7 +2279,7 @@ fseg_alloc_free_page_low( reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr); - space_header = fsp_get_space_header(space, page_size, mtr); + space_header = fsp_get_space_header(space, mtr); descr = xdes_get_descriptor_with_space_hdr(space_header, space, hint, mtr); @@ -2345,7 +2288,7 @@ fseg_alloc_free_page_low( hint */ /* The file space header page is always allocated. */ hint = 0; - descr = xdes_get_descriptor(space, hint, page_size, mtr); + descr = xdes_get_descriptor(space, hint, mtr); } /* In the big if-else below we look for ret_page and ret_descr */ @@ -2372,7 +2315,7 @@ take_hinted_page: ========================================================= the hinted page ===============*/ - ret_descr = fsp_alloc_free_extent(space, page_size, hint, mtr); + ret_descr = fsp_alloc_free_extent(space, hint, mtr); ut_a(ret_descr == descr); @@ -2382,7 +2325,7 @@ take_hinted_page: ret_descr + XDES_FLST_NODE, mtr); /* Try to fill the segment free list */ - fseg_fill_free_list(seg_inode, space, page_size, + fseg_fill_free_list(seg_inode, space, hint + FSP_EXTENT_SIZE, mtr); goto take_hinted_page; /*-----------------------------------------------------------*/ @@ -2390,8 +2333,7 @@ take_hinted_page: && ((reserved - used) < reserved / FSEG_FILLFACTOR) && (used >= FSEG_FRAG_LIMIT) && (!!(ret_descr - = fseg_alloc_free_extent( - seg_inode, space, page_size, mtr)))) { + = fseg_alloc_free_extent(seg_inode, space, mtr)))) { /* 3. We take any free extent (which was already assigned above =============================================================== @@ -2437,8 +2379,7 @@ take_hinted_page: return(NULL); } - ret_descr = xdes_lst_get_descriptor(space, page_size, - first, mtr); + ret_descr = xdes_lst_get_descriptor(space, first, mtr); ret_page = xdes_get_offset(ret_descr) + xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE, 0, mtr); @@ -2448,7 +2389,7 @@ take_hinted_page: /* 6. We allocate an individual page from the space ===================================================*/ buf_block_t* block = fsp_alloc_free_page( - space, page_size, hint, rw_latch, mtr, init_mtr); + space, hint, rw_latch, mtr, init_mtr); ut_ad(!has_done_reservation || block != NULL); @@ -2470,8 +2411,7 @@ take_hinted_page: } else { /* 7. We allocate a new extent and take its first page ======================================================*/ - ret_descr = fseg_alloc_free_extent(seg_inode, - space, page_size, mtr); + ret_descr = fseg_alloc_free_extent(seg_inode, space, mtr); if (ret_descr == NULL) { ret_page = FIL_NULL; @@ -2519,8 +2459,7 @@ got_hinted_page: The extent is still in the appropriate list (FSEG_NOT_FULL or FSEG_FREE), and the page is not yet marked as used. */ - ut_ad(xdes_get_descriptor(space, ret_page, page_size, mtr) - == ret_descr); + ut_ad(xdes_get_descriptor(space, ret_page, mtr) == ret_descr); ut_ad(xdes_mtr_get_bit( ret_descr, XDES_FREE_BIT, @@ -2529,8 +2468,7 @@ got_hinted_page: fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr); } - return(fsp_page_create(space, ret_page, page_size, rw_latch, - mtr, init_mtr)); + return fsp_page_create(space, ret_page, rw_latch, mtr, init_mtr); } /**********************************************************************//** @@ -2572,9 +2510,8 @@ fseg_alloc_free_page_general( space_id = page_get_space_id(page_align(seg_header)); space = mtr_x_lock_space(space_id, mtr); - const page_size_t page_size(space->flags); - - inode = fseg_inode_get(seg_header, space_id, page_size, mtr, &iblock); + inode = fseg_inode_get(seg_header, space_id, space->zip_size(), + mtr, &iblock); fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr); if (!has_done_reservation @@ -2583,7 +2520,7 @@ fseg_alloc_free_page_general( return(NULL); } - block = fseg_alloc_free_page_low(space, page_size, + block = fseg_alloc_free_page_low(space, inode, hint, direction, RW_X_LATCH, mtr, init_mtr #ifdef UNIV_DEBUG @@ -2701,9 +2638,9 @@ fsp_reserve_free_extents( *n_reserved = n_ext; mtr_x_lock(&space->latch, mtr); - const page_size_t page_size(space->flags); + const ulint physical_size = space->physical_size(); - space_header = fsp_get_space_header(space, page_size, mtr); + space_header = fsp_get_space_header(space, mtr); try_again: size = mach_read_from_4(space_header + FSP_SIZE); ut_ad(size == space->size_in_header); @@ -2735,8 +2672,7 @@ try_again: if (n_free_up > 0) { n_free_up--; - n_free_up -= n_free_up / (page_size.physical() - / FSP_EXTENT_SIZE); + n_free_up -= n_free_up / (physical_size / FSP_EXTENT_SIZE); } n_free = n_free_list_ext + n_free_up; @@ -2844,7 +2780,6 @@ fseg_mark_page_used( @param[in] seg_inode segment inode @param[in,out] space tablespace @param[in] offset page number -@param[in] page_size page size @param[in] ahi whether we may need to drop the adaptive hash index @param[in,out] mtr mini-transaction */ @@ -2854,7 +2789,6 @@ fseg_free_page_low( fseg_inode_t* seg_inode, fil_space_t* space, page_no_t offset, - const page_size_t& page_size, #ifdef BTR_CUR_HASH_ADAPT bool ahi, #endif /* BTR_CUR_HASH_ADAPT */ @@ -2883,7 +2817,7 @@ fseg_free_page_low( } #endif /* BTR_CUR_HASH_ADAPT */ - descr = xdes_get_descriptor(space, offset, page_size, mtr); + descr = xdes_get_descriptor(space, offset, mtr); if (xdes_mtr_get_bit(descr, XDES_FREE_BIT, offset % FSP_EXTENT_SIZE, mtr)) { @@ -2911,8 +2845,7 @@ fseg_free_page_low( } } - fsp_free_page(space, offset, page_size, mtr); - + fsp_free_page(space, offset, mtr); return; } @@ -2962,13 +2895,13 @@ fseg_free_page_low( /* The extent has become free: free it to space */ flst_remove(seg_inode + FSEG_NOT_FULL, descr + XDES_FLST_NODE, mtr); - fsp_free_extent(space, offset, page_size, mtr); + fsp_free_extent(space, offset, mtr); } } #ifndef BTR_CUR_HASH_ADAPT -# define fseg_free_page_low(inode, space, offset, page_size, ahi, mtr) \ - fseg_free_page_low(inode, space, offset, page_size, mtr) +# define fseg_free_page_low(inode, space, offset, ahi, mtr) \ + fseg_free_page_low(inode, space, offset, mtr) #endif /* !BTR_CUR_HASH_ADAPT */ /**********************************************************************//** @@ -2988,16 +2921,16 @@ fseg_free_page_func( fseg_inode_t* seg_inode; buf_block_t* iblock; fil_space_t* space = mtr_x_lock_space(space_id, mtr); - const page_size_t page_size(space->flags); DBUG_LOG("fseg_free_page", "space_id: " << space_id << ", page_no: " << page); - seg_inode = fseg_inode_get(seg_header, space_id, page_size, mtr, + seg_inode = fseg_inode_get(seg_header, space_id, space->zip_size(), + mtr, &iblock); fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr); - fseg_free_page_low(seg_inode, space, page, page_size, ahi, mtr); + fseg_free_page_low(seg_inode, space, page, ahi, mtr); ut_d(buf_page_set_file_page_was_freed(page_id_t(space_id, page))); @@ -3013,8 +2946,8 @@ fseg_page_is_free(fil_space_t* space, unsigned page) { bool is_free; mtr_t mtr; - page_size_t page_size(space->flags); - page_no_t dpage = xdes_calc_descriptor_page(page_size, page); + page_no_t dpage = xdes_calc_descriptor_page(space->zip_size(), + page); mtr.start(); mtr_s_lock(&space->latch, &mtr); @@ -3022,7 +2955,7 @@ fseg_page_is_free(fil_space_t* space, unsigned page) if (page >= space->free_limit || page >= space->size_in_header) { is_free = true; } else if (const xdes_t* descr = xdes_get_descriptor_const( - space, dpage, page, page_size, &mtr)) { + space, dpage, page, &mtr)) { is_free = xdes_get_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE); } else { @@ -3036,7 +2969,6 @@ fseg_page_is_free(fil_space_t* space, unsigned page) /** Free an extent of a segment to the space free list. @param[in,out] seg_inode segment inode @param[in,out] space tablespace -@param[in] page_size page size @param[in] page page number in the extent @param[in] ahi whether we may need to drop the adaptive hash index @@ -3047,7 +2979,6 @@ void fseg_free_extent( fseg_inode_t* seg_inode, fil_space_t* space, - const page_size_t& page_size, ulint page, #ifdef BTR_CUR_HASH_ADAPT bool ahi, @@ -3062,7 +2993,7 @@ fseg_free_extent( ut_ad(mtr != NULL); - descr = xdes_get_descriptor(space, page, page_size, mtr); + descr = xdes_get_descriptor(space, page, mtr); ut_a(xdes_get_state(descr, mtr) == XDES_FSEG); ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8)); @@ -3109,7 +3040,7 @@ fseg_free_extent( MLOG_4BYTES, mtr); } - fsp_free_extent(space, page, page_size, mtr); + fsp_free_extent(space, page, mtr); #ifdef UNIV_DEBUG for (i = 0; i < FSP_EXTENT_SIZE; i++) { @@ -3121,8 +3052,8 @@ fseg_free_extent( } #ifndef BTR_CUR_HASH_ADAPT -# define fseg_free_extent(inode, space, page_size, page, ahi, mtr) \ - fseg_free_extent(inode, space, page_size, page, mtr) +# define fseg_free_extent(inode, space, page, ahi, mtr) \ + fseg_free_extent(inode, space, page, mtr) #endif /* !BTR_CUR_HASH_ADAPT */ /**********************************************************************//** @@ -3156,9 +3087,8 @@ fseg_free_step_func( header_page = page_get_page_no(page_align(header)); fil_space_t* space = mtr_x_lock_space(space_id, mtr); - const page_size_t page_size(space->flags); - descr = xdes_get_descriptor(space, header_page, page_size, mtr); + descr = xdes_get_descriptor(space, header_page, mtr); /* Check that the header resides on a page which has not been freed yet */ @@ -3166,8 +3096,8 @@ fseg_free_step_func( ut_a(xdes_mtr_get_bit(descr, XDES_FREE_BIT, header_page % FSP_EXTENT_SIZE, mtr) == FALSE); buf_block_t* iblock; - - inode = fseg_inode_try_get(header, space_id, page_size, mtr, &iblock); + const ulint zip_size = space->zip_size(); + inode = fseg_inode_try_get(header, space_id, zip_size, mtr, &iblock); if (inode == NULL) { ib::info() << "Double free of inode from " @@ -3176,14 +3106,12 @@ fseg_free_step_func( } fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr); - descr = fseg_get_first_extent(inode, space, page_size, mtr); + descr = fseg_get_first_extent(inode, space, mtr); if (descr != NULL) { /* Free the extent held by the segment */ page = xdes_get_offset(descr); - - fseg_free_extent(inode, space, page_size, page, ahi, mtr); - + fseg_free_extent(inode, space, page, ahi, mtr); DBUG_RETURN(FALSE); } @@ -3192,7 +3120,7 @@ fseg_free_step_func( if (n == ULINT_UNDEFINED) { /* Freeing completed: free the segment inode */ - fsp_free_seg_inode(space, page_size, inode, mtr); + fsp_free_seg_inode(space, inode, mtr); DBUG_RETURN(TRUE); } @@ -3200,13 +3128,13 @@ fseg_free_step_func( fseg_free_page_low( inode, space, fseg_get_nth_frag_page_no(inode, n, mtr), - page_size, ahi, mtr); + ahi, mtr); n = fseg_find_last_used_frag_page_slot(inode, mtr); if (n == ULINT_UNDEFINED) { /* Freeing completed: free the segment inode */ - fsp_free_seg_inode(space, page_size, inode, mtr); + fsp_free_seg_inode(space, inode, mtr); DBUG_RETURN(TRUE); } @@ -3239,19 +3167,19 @@ fseg_free_step_not_header_func( ut_ad(mtr->is_named_space(space_id)); fil_space_t* space = mtr_x_lock_space(space_id, mtr); - const page_size_t page_size(space->flags); buf_block_t* iblock; - inode = fseg_inode_get(header, space_id, page_size, mtr, &iblock); + inode = fseg_inode_get(header, space_id, space->zip_size(), mtr, + &iblock); fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr); - descr = fseg_get_first_extent(inode, space, page_size, mtr); + descr = fseg_get_first_extent(inode, space, mtr); if (descr != NULL) { /* Free the extent held by the segment */ page = xdes_get_offset(descr); - fseg_free_extent(inode, space, page_size, page, ahi, mtr); + fseg_free_extent(inode, space, page, ahi, mtr); return(FALSE); } @@ -3271,7 +3199,7 @@ fseg_free_step_not_header_func( return(TRUE); } - fseg_free_page_low(inode, space, page_no, page_size, ahi, mtr); + fseg_free_page_low(inode, space, page_no, ahi, mtr); return(FALSE); } @@ -3281,7 +3209,6 @@ We think of the extent lists of the segment catenated in the order FSEG_FULL -> FSEG_NOT_FULL -> FSEG_FREE. @param[in] inode segment inode @param[in] space tablespace -@param[in] page_size page size @param[in,out] mtr mini-transaction @return the first extent descriptor, or NULL if none */ MY_ATTRIBUTE((nonnull, warn_unused_result)) @@ -3290,7 +3217,6 @@ xdes_t* fseg_get_first_extent( fseg_inode_t* inode, const fil_space_t* space, - const page_size_t& page_size, mtr_t* mtr) { fil_addr_t first; @@ -3316,7 +3242,7 @@ fseg_get_first_extent( ut_ad(first.page != FIL_NULL); return(first.page == FIL_NULL ? NULL - : xdes_lst_get_descriptor(space, page_size, first, mtr)); + : xdes_lst_get_descriptor(space, first, mtr)); } #ifdef UNIV_BTR_PRINT @@ -3380,9 +3306,8 @@ fseg_print( space_id = page_get_space_id(page_align(header)); const fil_space_t* space = mtr_x_lock_space(space_id, mtr); - const page_size_t page_size(space->flags); - inode = fseg_inode_get(header, space_id, page_size, mtr); + inode = fseg_inode_get(header, space_id, space->zip_size(), mtr); fseg_print_low(inode, mtr); } diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index d5ce2f30ab4..d7695b7e9cc 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -3273,7 +3273,7 @@ fts_fetch_doc_from_rec( doc->text.f_str = btr_rec_copy_externally_stored_field( clust_rec, offsets, - btr_pcur_get_block(pcur)->page.size, + btr_pcur_get_block(pcur)->zip_size(), clust_pos, &doc->text.f_len, static_cast( doc->self_heap->arg)); @@ -7456,7 +7456,7 @@ fts_init_recover_doc( doc.text.f_str = btr_copy_externally_stored_field( &doc.text.f_len, static_cast(dfield_get_data(dfield)), - dict_table_page_size(table), len, + table->space->zip_size(), len, static_cast(doc.self_heap->arg)); } else { doc.text.f_str = static_cast( diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 00f3b9aedf0..bf7e262ac98 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -206,7 +206,7 @@ struct fts_phrase_t { distance(0), charset(NULL), heap(NULL), - page_size(dict_table_page_size(table)), + zip_size(table->space->zip_size()), proximity_pos(NULL), parser(NULL) { @@ -230,8 +230,8 @@ struct fts_phrase_t { /** Heap for word processing */ mem_heap_t* heap; - /** Row page size */ - const page_size_t page_size; + /** ROW_FORMAT=COMPRESSED page size, or 0 */ + const ulint zip_size; /** Position info for proximity search verification. Records the min and max position of words matched */ @@ -2013,7 +2013,7 @@ fts_query_fetch_document( if (dfield_is_ext(dfield)) { data = btr_copy_externally_stored_field( - &cur_len, data, phrase->page_size, + &cur_len, data, phrase->zip_size, dfield_get_len(dfield), phrase->heap); } else { cur_len = dfield_get_len(dfield); diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc index 05474b02cbd..66e35c6e2c4 100644 --- a/storage/innobase/fut/fut0lst.cc +++ b/storage/innobase/fut/fut0lst.cc @@ -120,13 +120,11 @@ flst_add_last( if (last_addr.page == node_addr.page) { last_node = page_align(node) + last_addr.boffset; } else { - bool found; - const page_size_t& page_size - = fil_space_get_page_size(space, &found); + fil_space_t* s = fil_space_acquire_silent(space); + ulint zip_size = s ? s->zip_size() : 0; + if (s) s->release(); - ut_ad(found); - - last_node = fut_get_ptr(space, page_size, last_addr, + last_node = fut_get_ptr(space, zip_size, last_addr, RW_SX_LATCH, mtr); } @@ -170,13 +168,11 @@ flst_add_first( if (first_addr.page == node_addr.page) { first_node = page_align(node) + first_addr.boffset; } else { - bool found; - const page_size_t& page_size - = fil_space_get_page_size(space, &found); + fil_space_t* s = fil_space_acquire_silent(space); + ulint zip_size = s ? s->zip_size() : 0; + if (s) s->release(); - ut_ad(found); - - first_node = fut_get_ptr(space, page_size, first_addr, + first_node = fut_get_ptr(space, zip_size, first_addr, RW_SX_LATCH, mtr); } @@ -230,13 +226,11 @@ flst_insert_after( if (!fil_addr_is_null(node3_addr)) { /* Update prev field of node3 */ - bool found; - const page_size_t& page_size - = fil_space_get_page_size(space, &found); + fil_space_t* s = fil_space_acquire_silent(space); + ulint zip_size = s ? s->zip_size() : 0; + if (s) s->release(); - ut_ad(found); - - node3 = fut_get_ptr(space, page_size, + node3 = fut_get_ptr(space, zip_size, node3_addr, RW_SX_LATCH, mtr); flst_write_addr(node3 + FLST_PREV, node2_addr, mtr); } else { @@ -294,14 +288,12 @@ flst_insert_before( flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr); if (!fil_addr_is_null(node1_addr)) { - bool found; - const page_size_t& page_size - = fil_space_get_page_size(space, &found); - - ut_ad(found); + fil_space_t* s = fil_space_acquire_silent(space); + ulint zip_size = s ? s->zip_size() : 0; + if (s) s->release(); /* Update next field of node1 */ - node1 = fut_get_ptr(space, page_size, node1_addr, + node1 = fut_get_ptr(space, zip_size, node1_addr, RW_SX_LATCH, mtr); flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr); } else { @@ -344,11 +336,9 @@ flst_remove( buf_ptr_get_fsp_addr(node2, &space, &node2_addr); - bool found; - const page_size_t& page_size = fil_space_get_page_size(space, - &found); - - ut_ad(found); + fil_space_t* s = fil_space_acquire_silent(space); + ulint zip_size = s ? s->zip_size() : 0; + if (s) s->release(); node1_addr = flst_get_prev_addr(node2, mtr); node3_addr = flst_get_next_addr(node2, mtr); @@ -361,7 +351,7 @@ flst_remove( node1 = page_align(node2) + node1_addr.boffset; } else { - node1 = fut_get_ptr(space, page_size, + node1 = fut_get_ptr(space, zip_size, node1_addr, RW_SX_LATCH, mtr); } @@ -380,7 +370,7 @@ flst_remove( node3 = page_align(node2) + node3_addr.boffset; } else { - node3 = fut_get_ptr(space, page_size, + node3 = fut_get_ptr(space, zip_size, node3_addr, RW_SX_LATCH, mtr); } @@ -431,11 +421,9 @@ flst_validate( /* Find out the space id */ buf_ptr_get_fsp_addr(base, &space, &base_addr); - bool found; - const page_size_t& page_size = fil_space_get_page_size(space, - &found); - - ut_ad(found); + fil_space_t* s = fil_space_acquire_silent(space); + ulint zip_size = s ? s->zip_size() : 0; + if (s) s->release(); len = flst_get_len(base); node_addr = flst_get_first(base, mtr1); @@ -443,7 +431,7 @@ flst_validate( for (i = 0; i < len; i++) { mtr_start(&mtr2); - node = fut_get_ptr(space, page_size, + node = fut_get_ptr(space, zip_size, node_addr, RW_SX_LATCH, &mtr2); node_addr = flst_get_next_addr(node, &mtr2); @@ -458,7 +446,7 @@ flst_validate( for (i = 0; i < len; i++) { mtr_start(&mtr2); - node = fut_get_ptr(space, page_size, + node = fut_get_ptr(space, zip_size, node_addr, RW_SX_LATCH, &mtr2); node_addr = flst_get_prev_addr(node, &mtr2); diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index 9c10108a3f3..d77e29d308e 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -746,14 +746,14 @@ rtr_adjust_upper_level( prev_page_no = btr_page_get_prev(page, mtr); next_page_no = btr_page_get_next(page, mtr); space = block->page.id.space(); - ut_ad(block->page.size.equals_to(dict_table_page_size(index->table))); + ut_ad(block->zip_size() == index->table->space->zip_size()); /* Update page links of the level */ if (prev_page_no != FIL_NULL) { page_id_t prev_page_id(space, prev_page_no); buf_block_t* prev_block = btr_block_get( - prev_page_id, block->page.size, RW_X_LATCH, + prev_page_id, block->zip_size(), RW_X_LATCH, index, mtr); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(prev_block->frame) == page_is_comp(page)); @@ -770,7 +770,7 @@ rtr_adjust_upper_level( page_id_t next_page_id(space, next_page_no); buf_block_t* next_block = btr_block_get( - next_page_id, block->page.size, RW_X_LATCH, + next_page_id, block->zip_size(), RW_X_LATCH, index, mtr); #ifdef UNIV_BTR_DEBUG ut_a(page_is_comp(next_block->frame) == page_is_comp(page)); @@ -1875,7 +1875,7 @@ rtr_estimate_n_rows_in_range( buf_block_t* block = btr_block_get( page_id_t(index->table->space_id, index->page), - page_size_t(index->table->space->flags), + index->table->space->zip_size(), RW_S_LATCH, index, &mtr); const page_t* page = buf_block_get_frame(block); const unsigned n_recs = page_header_get_field(page, PAGE_N_RECS); diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index a406acabf6e..84d07b5ac52 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -145,7 +145,7 @@ rtr_pcur_getnext_from_path( | MTR_MEMO_X_LOCK)); } - const page_size_t page_size(index->table->space->flags); + const ulint zip_size = index->table->space->zip_size(); /* Pop each node/page to be searched from "path" structure and do a search on it. Please note, any pages that are in @@ -269,7 +269,7 @@ rtr_pcur_getnext_from_path( block = buf_page_get_gen( page_id_t(index->table->space_id, - next_rec.page_no), page_size, + next_rec.page_no), zip_size, rw_latch, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err); if (block == NULL) { @@ -424,7 +424,7 @@ rtr_pcur_getnext_from_path( block, page_id_t(index->table->space_id, block->page.id.page_no()), - page_size, BTR_MODIFY_TREE, + zip_size, BTR_MODIFY_TREE, btr_cur, mtr); } @@ -1344,8 +1344,7 @@ rtr_cur_restore_position( page_cur_t* page_cursor; node_visit_t* node = rtr_get_parent_node(btr_cur, level, false); node_seq_t path_ssn = node->seq_no; - const page_size_t page_size(index->table->space->flags); - + const ulint zip_size = index->table->space->zip_size(); ulint page_no = node->page_no; heap = mem_heap_create(256); @@ -1361,7 +1360,7 @@ search_again: block = buf_page_get_gen( page_id_t(index->table->space_id, page_no), - page_size, RW_X_LATCH, NULL, + zip_size, RW_X_LATCH, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err); ut_ad(block); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 153390dbc2d..29da9e0cad6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3842,11 +3842,6 @@ static int innodb_init_params() DBUG_RETURN(HA_ERR_INITIALIZATION); } - /* This is the first time univ_page_size is used. - It was initialized to 16k pages before srv_page_size was set */ - univ_page_size.copy_from( - page_size_t(srv_page_size, srv_page_size, false)); - srv_sys_space.set_space_id(TRX_SYS_SPACE); srv_sys_space.set_flags(FSP_FLAGS_PAGE_SSIZE()); srv_sys_space.set_name("innodb_system"); @@ -13834,7 +13829,7 @@ fsp_get_available_space_in_free_extents(const fil_space_t& space) ulint n_free_up = (size_in_header - space.free_limit) / FSP_EXTENT_SIZE; - const ulint size = page_size_t(space.flags).physical(); + const ulint size = space.physical_size(); if (n_free_up > 0) { n_free_up--; n_free_up -= n_free_up / (size / FSP_EXTENT_SIZE); @@ -13984,8 +13979,7 @@ ha_innobase::info_low( stats.records = (ha_rows) n_rows; stats.deleted = 0; if (fil_space_t* space = ib_table->space) { - const ulint size = page_size_t(space->flags) - .physical(); + const ulint size = space->physical_size(); stats.data_file_length = ulonglong(stat_clustered_index_size) * size; @@ -17446,7 +17440,7 @@ innodb_make_page_dirty(THD*, st_mysql_sys_var*, void*, const void* save) buf_block_t* block = buf_page_get( page_id_t(space_id, srv_saved_page_number_debug), - page_size_t(space->flags), RW_X_LATCH, &mtr); + space->zip_size(), RW_X_LATCH, &mtr); if (block != NULL) { byte* page = block->frame; @@ -20637,9 +20631,9 @@ innobase_get_computed_value( dfield_t* field; ulint len; - const page_size_t page_size = (old_table == NULL) - ? dict_table_page_size(index->table) - : dict_table_page_size(old_table); + const ulint zip_size = old_table + ? old_table->space->zip_size() + : dict_tf_get_zip_size(index->table->flags); ulint ret = 0; @@ -20691,7 +20685,7 @@ innobase_get_computed_value( } data = btr_copy_externally_stored_field( - &len, data, page_size, + &len, data, zip_size, dfield_get_len(row_field), *local_heap); } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 38353554be4..3abb62299e4 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -10216,7 +10216,7 @@ commit_cache_norebuild( mtr.start(); if (buf_block_t* b = buf_page_get( page_id_t(space->id, 0), - page_size_t(space->flags), + space->zip_size(), RW_X_LATCH, &mtr)) { mtr.set_named_space(space); mlog_write_ulint( diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index cedb6e05782..bbbff16796f 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -5978,7 +5978,7 @@ i_s_dict_fill_sys_tables( ulint compact = DICT_TF_GET_COMPACT(table->flags); ulint atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS( table->flags); - const page_size_t& page_size = dict_tf_get_page_size(table->flags); + const ulint zip_size = dict_tf_get_zip_size(table->flags); const char* row_format; if (!compact) { @@ -6007,10 +6007,7 @@ i_s_dict_fill_sys_tables( OK(field_store_string(fields[SYS_TABLES_ROW_FORMAT], row_format)); - OK(fields[SYS_TABLES_ZIP_PAGE_SIZE]->store( - page_size.is_compressed() - ? page_size.physical() - : 0, true)); + OK(fields[SYS_TABLES_ZIP_PAGE_SIZE]->store(zip_size, true)); OK(field_store_string(fields[SYS_TABLES_SPACE_TYPE], table->space_id ? "Single" : "System")); @@ -8003,13 +8000,11 @@ i_s_dict_fill_sys_tablespaces( DBUG_RETURN(0); } - const page_size_t page_size(cflags); - OK(fields[SYS_TABLESPACES_PAGE_SIZE]->store( - page_size.logical(), true)); + fil_space_t::logical_size(cflags), true)); OK(fields[SYS_TABLESPACES_ZIP_PAGE_SIZE]->store( - page_size.physical(), true)); + fil_space_t::physical_size(cflags), true)); char* filepath = NULL; if (FSP_FLAGS_HAS_DATA_DIR(cflags)) { diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 1c90e8dd5c8..dd60d5c8096 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2018, MariaDB Corporation. +Copyright (c) 2016, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -363,8 +363,7 @@ ibuf_header_page_get( block = buf_page_get( page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO), - univ_page_size, RW_X_LATCH, mtr); - + 0, RW_X_LATCH, mtr); if (!block->page.encrypted) { buf_block_dbg_add_level(block, SYNC_IBUF_HEADER); @@ -395,7 +394,7 @@ ibuf_tree_root_get( /* only segment list access is exclusive each other */ block = buf_page_get( page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO), - univ_page_size, RW_SX_LATCH, mtr); + 0, RW_SX_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); @@ -539,7 +538,7 @@ ibuf_init_at_db_start(void) block = buf_page_get( page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO), - univ_page_size, RW_X_LATCH, &mtr); + 0, RW_X_LATCH, &mtr); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); @@ -602,7 +601,7 @@ ibuf_bitmap_page_init( /* Write all zeros to the bitmap */ compile_time_assert(!(IBUF_BITS_PER_PAGE % 2)); - byte_offset = UT_BITS_IN_BYTES(block->page.size.physical() + byte_offset = UT_BITS_IN_BYTES(block->physical_size() * IBUF_BITS_PER_PAGE); memset(page + IBUF_BITMAP, 0, byte_offset); @@ -636,31 +635,31 @@ ibuf_parse_bitmap_init( /** Gets the desired bits for a given page from a bitmap page. @param[in] page bitmap page @param[in] page_id page id whose bits to get -@param[in] page_size page id whose bits to get +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ... @param[in,out] mtr mini-transaction holding an x-latch on the bitmap page @return value of bits */ -# define ibuf_bitmap_page_get_bits(page, page_id, page_size, bit, mtr) \ - ibuf_bitmap_page_get_bits_low(page, page_id, page_size, \ +# define ibuf_bitmap_page_get_bits(page, page_id, zip_size, bit, mtr) \ + ibuf_bitmap_page_get_bits_low(page, page_id, zip_size, \ MTR_MEMO_PAGE_X_FIX, mtr, bit) # else /* UNIV_DEBUG */ /** Gets the desired bits for a given page from a bitmap page. @param[in] page bitmap page @param[in] page_id page id whose bits to get -@param[in] page_size page id whose bits to get +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ... @param[in,out] mtr mini-transaction holding an x-latch on the bitmap page @return value of bits */ -# define ibuf_bitmap_page_get_bits(page, page_id, page_size, bit, mtr) \ - ibuf_bitmap_page_get_bits_low(page, page_id, page_size, bit) +# define ibuf_bitmap_page_get_bits(page, page_id, zip_size, bit, mtr) \ + ibuf_bitmap_page_get_bits_low(page, page_id, zip_size, bit) # endif /* UNIV_DEBUG */ /** Gets the desired bits for a given page from a bitmap page. @param[in] page bitmap page @param[in] page_id page id whose bits to get -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] latch_type MTR_MEMO_PAGE_X_FIX, MTR_MEMO_BUF_FIX, ... @param[in,out] mtr mini-transaction holding latch_type on the bitmap page @@ -671,7 +670,7 @@ ulint ibuf_bitmap_page_get_bits_low( const page_t* page, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, #ifdef UNIV_DEBUG ulint latch_type, mtr_t* mtr, @@ -682,12 +681,14 @@ ibuf_bitmap_page_get_bits_low( ulint bit_offset; ulint map_byte; ulint value; + const ulint size = zip_size ? zip_size : srv_page_size; + ut_ad(ut_is_2pow(zip_size)); ut_ad(bit < IBUF_BITS_PER_PAGE); compile_time_assert(!(IBUF_BITS_PER_PAGE % 2)); ut_ad(mtr_memo_contains_page(mtr, page, latch_type)); - bit_offset = (page_id.page_no() % page_size.physical()) + bit_offset = (page_id.page_no() & (size - 1)) * IBUF_BITS_PER_PAGE + bit; byte_offset = bit_offset / 8; @@ -711,7 +712,7 @@ ibuf_bitmap_page_get_bits_low( /** Sets the desired bit for a given page in a bitmap page. @param[in,out] page bitmap page @param[in] page_id page id whose bits to set -@param[in] page_size page size +@param[in] physical_size page size @param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ... @param[in] val value to set @param[in,out] mtr mtr containing an x-latch to the bitmap page */ @@ -720,7 +721,7 @@ void ibuf_bitmap_page_set_bits( page_t* page, const page_id_t page_id, - const page_size_t& page_size, + ulint physical_size, ulint bit, ulint val, mtr_t* mtr) @@ -738,7 +739,7 @@ ibuf_bitmap_page_set_bits( || (0 == ibuf_count_get(page_id))); #endif - bit_offset = (page_id.page_no() % page_size.physical()) + bit_offset = (page_id.page_no() % physical_size) * IBUF_BITS_PER_PAGE + bit; byte_offset = bit_offset / 8; @@ -765,26 +766,20 @@ ibuf_bitmap_page_set_bits( /** Calculates the bitmap page number for a given page number. @param[in] page_id page id -@param[in] page_size page size +@param[in] size page size @return the bitmap page id where the file page is mapped */ -UNIV_INLINE -const page_id_t -ibuf_bitmap_page_no_calc( - const page_id_t page_id, - const page_size_t& page_size) +inline page_id_t ibuf_bitmap_page_no_calc(const page_id_t page_id, ulint size) { - ulint bitmap_page_no; + if (!size) size = srv_page_size; - bitmap_page_no = FSP_IBUF_BITMAP_OFFSET - + (page_id.page_no() & ~(page_size.physical() - 1)); - - return(page_id_t(page_id.space(), bitmap_page_no)); + return page_id_t(page_id.space(), FSP_IBUF_BITMAP_OFFSET + + (page_id.page_no() & ~(size - 1))); } /** Gets the ibuf bitmap page where the bits describing a given file page are stored. @param[in] page_id page id of the file page -@param[in] page_size page size of the file page +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] file file name @param[in] line line where called @param[in,out] mtr mini-transaction @@ -795,7 +790,7 @@ static page_t* ibuf_bitmap_get_map_page_func( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, const char* file, unsigned line, mtr_t* mtr) @@ -803,8 +798,8 @@ ibuf_bitmap_get_map_page_func( buf_block_t* block = NULL; dberr_t err = DB_SUCCESS; - block = buf_page_get_gen(ibuf_bitmap_page_no_calc(page_id, page_size), - page_size, RW_X_LATCH, NULL, BUF_GET, + block = buf_page_get_gen(ibuf_bitmap_page_no_calc(page_id, zip_size), + zip_size, RW_X_LATCH, NULL, BUF_GET, file, line, mtr, &err); if (err != DB_SUCCESS) { @@ -820,13 +815,13 @@ ibuf_bitmap_get_map_page_func( /** Gets the ibuf bitmap page where the bits describing a given file page are stored. @param[in] page_id page id of the file page -@param[in] page_size page size of the file page +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] mtr mini-transaction @return bitmap page where the file page is mapped, that is, the bitmap page containing the descriptor bits for the file page; the bitmap page is x-latched */ -#define ibuf_bitmap_get_map_page(page_id, page_size, mtr) \ - ibuf_bitmap_get_map_page_func(page_id, page_size, \ +#define ibuf_bitmap_get_map_page(page_id, zip_size, mtr) \ + ibuf_bitmap_get_map_page_func(page_id, zip_size, \ __FILE__, __LINE__, mtr) /************************************************************************//** @@ -860,14 +855,14 @@ ibuf_set_free_bits_low( } bitmap_page = ibuf_bitmap_get_map_page(block->page.id, - block->page.size, mtr); + block->zip_size(), mtr); #ifdef UNIV_IBUF_DEBUG ut_a(val <= ibuf_index_page_calc_free(block)); #endif /* UNIV_IBUF_DEBUG */ ibuf_bitmap_page_set_bits( - bitmap_page, block->page.id, block->page.size, + bitmap_page, block->page.id, block->physical_size(), IBUF_BITMAP_FREE, val, mtr); } @@ -904,7 +899,7 @@ ibuf_set_free_bits_func( block->page.id.space()); bitmap_page = ibuf_bitmap_get_map_page(block->page.id, - block->page.size, &mtr); + block->zip_size(), &mtr); switch (space->purpose) { case FIL_TYPE_LOG: @@ -946,7 +941,7 @@ ibuf_set_free_bits_func( #endif /* UNIV_IBUF_DEBUG */ ibuf_bitmap_page_set_bits( - bitmap_page, block->page.id, block->page.size, + bitmap_page, block->page.id, block->physical_size(), IBUF_BITMAP_FREE, val, &mtr); mtr_commit(&mtr); @@ -996,7 +991,7 @@ ibuf_update_free_bits_low( ut_a(!buf_block_get_page_zip(block)); ut_ad(mtr->is_named_space(block->page.id.space())); - before = ibuf_index_page_calc_free_bits(block->page.size.logical(), + before = ibuf_index_page_calc_free_bits(srv_page_size, max_ins_size); after = ibuf_index_page_calc_free(block); @@ -1031,10 +1026,10 @@ ibuf_update_free_bits_zip( buf_frame_t* frame = buf_block_get_frame(block); ut_a(frame); ut_a(page_is_leaf(frame)); - ut_a(block->page.size.is_compressed()); + ut_a(block->zip_size()); bitmap_page = ibuf_bitmap_get_map_page(block->page.id, - block->page.size, mtr); + block->zip_size(), mtr); after = ibuf_index_page_calc_free_zip(block); @@ -1048,7 +1043,7 @@ ibuf_update_free_bits_zip( } ibuf_bitmap_page_set_bits( - bitmap_page, block->page.id, block->page.size, + bitmap_page, block->page.id, block->physical_size(), IBUF_BITMAP_FREE, after, mtr); } @@ -1090,23 +1085,19 @@ ibuf_update_free_bits_for_two_pages_low( /** Returns TRUE if the page is one of the fixed address ibuf pages. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @return TRUE if a fixed address ibuf i/o page */ -UNIV_INLINE -ibool -ibuf_fixed_addr_page( - const page_id_t page_id, - const page_size_t& page_size) +inline bool ibuf_fixed_addr_page(const page_id_t page_id, ulint zip_size) { return((page_id.space() == IBUF_SPACE_ID && page_id.page_no() == IBUF_TREE_ROOT_PAGE_NO) - || ibuf_bitmap_page(page_id, page_size)); + || ibuf_bitmap_page(page_id, zip_size)); } /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. Must not be called when recv_no_ibuf_operations==true. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] x_latch FALSE if relaxed check (avoid latching the bitmap page) @param[in] file file name @@ -1115,12 +1106,12 @@ bitmap page) bitmap page if the page is not one of the fixed address ibuf pages, or NULL, in which case a new transaction is created. @return TRUE if level 2 or level 3 page */ -ibool +bool ibuf_page_low( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, #ifdef UNIV_DEBUG - ibool x_latch, + bool x_latch, #endif /* UNIV_DEBUG */ const char* file, unsigned line, @@ -1133,12 +1124,10 @@ ibuf_page_low( ut_ad(!recv_no_ibuf_operations); ut_ad(x_latch || mtr == NULL); - if (ibuf_fixed_addr_page(page_id, page_size)) { - - return(TRUE); + if (ibuf_fixed_addr_page(page_id, zip_size)) { + return(true); } else if (page_id.space() != IBUF_SPACE_ID) { - - return(FALSE); + return(false); } compile_time_assert(IBUF_SPACE_ID == 0); @@ -1161,14 +1150,14 @@ ibuf_page_low( dberr_t err = DB_SUCCESS; buf_block_t* block = buf_page_get_gen( - ibuf_bitmap_page_no_calc(page_id, page_size), - page_size, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH, - file, line, &local_mtr, &err); + ibuf_bitmap_page_no_calc(page_id, zip_size), + zip_size, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH, + file, line, &local_mtr, &err); bitmap_page = buf_block_get_frame(block); ret = ibuf_bitmap_page_get_bits_low( - bitmap_page, page_id, page_size, + bitmap_page, page_id, zip_size, MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF); mtr_commit(&local_mtr); @@ -1181,10 +1170,10 @@ ibuf_page_low( mtr_start(mtr); } - bitmap_page = ibuf_bitmap_get_map_page_func(page_id, page_size, + bitmap_page = ibuf_bitmap_get_map_page_func(page_id, zip_size, file, line, mtr); - ret = ibuf_bitmap_page_get_bits(bitmap_page, page_id, page_size, + ret = ibuf_bitmap_page_get_bits(bitmap_page, page_id, zip_size, IBUF_BITMAP_IBUF, mtr); if (mtr == &local_mtr) { @@ -2057,11 +2046,11 @@ ibuf_add_free_page(void) (level 2 page) */ const page_id_t page_id(IBUF_SPACE_ID, block->page.id.page_no()); - bitmap_page = ibuf_bitmap_get_map_page(page_id, univ_page_size, &mtr); + bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr); mutex_exit(&ibuf_mutex); - ibuf_bitmap_page_set_bits(bitmap_page, page_id, univ_page_size, + ibuf_bitmap_page_set_bits(bitmap_page, page_id, srv_page_size, IBUF_BITMAP_IBUF, TRUE, &mtr); ibuf_mtr_commit(&mtr); @@ -2149,7 +2138,7 @@ ibuf_remove_free_page(void) { buf_block_t* block; - block = buf_page_get(page_id, univ_page_size, RW_X_LATCH, &mtr); + block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); @@ -2169,13 +2158,13 @@ ibuf_remove_free_page(void) /* Set the bit indicating that this page is no more an ibuf tree page (level 2 page) */ - bitmap_page = ibuf_bitmap_get_map_page(page_id, univ_page_size, &mtr); + bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr); mutex_exit(&ibuf_mutex); ibuf_bitmap_page_set_bits( - bitmap_page, page_id, univ_page_size, IBUF_BITMAP_IBUF, FALSE, - &mtr); + bitmap_page, page_id, srv_page_size, + IBUF_BITMAP_IBUF, FALSE, &mtr); ut_d(buf_page_set_file_page_was_freed(page_id)); @@ -3025,7 +3014,7 @@ ibuf_get_volume_buffered( block = buf_page_get( page_id_t(IBUF_SPACE_ID, prev_page_no), - univ_page_size, RW_X_LATCH, mtr); + 0, RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); @@ -3097,7 +3086,7 @@ count_later: block = buf_page_get( page_id_t(IBUF_SPACE_ID, next_page_no), - univ_page_size, RW_X_LATCH, mtr); + 0, RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE); @@ -3310,6 +3299,24 @@ ibuf_get_entry_counter_func( } } + +/** Translates the ibuf free bits to the free space on a page in bytes. +@param[in] physical_size page_size +@param[in] bits value for ibuf bitmap bits +@return maximum insert size after reorganize for the page */ +inline ulint +ibuf_index_page_calc_free_from_bits(ulint physical_size, ulint bits) +{ + ut_ad(bits < 4); + ut_ad(physical_size > IBUF_PAGE_SIZE_PER_FREE_SPACE); + + if (bits == 3) { + bits = 4; + } + + return bits * physical_size / IBUF_PAGE_SIZE_PER_FREE_SPACE; +} + /** Buffer an operation in the insert/delete buffer, instead of doing it directly to the disk page, if this is possible. @param[in] mode BTR_MODIFY_PREV or BTR_MODIFY_TREE @@ -3321,7 +3328,7 @@ buffering @param[in,out] index index where to insert; must not be unique or clustered @param[in] page_id page id where to insert -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] thr query thread @return DB_SUCCESS, DB_STRONG_FAIL or other error */ static MY_ATTRIBUTE((warn_unused_result)) @@ -3334,7 +3341,7 @@ ibuf_insert_low( ulint entry_size, dict_index_t* index, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, que_thr_t* thr) { big_rec_t* dummy_big_rec; @@ -3444,6 +3451,8 @@ ibuf_insert_low( ? &min_n_recs : NULL, &mtr); + const ulint physical_size = zip_size ? zip_size : srv_page_size; + if (op == IBUF_OP_DELETE && (min_n_recs < 2 || buf_pool_watch_occurred(page_id))) { /* The page could become empty after the record is @@ -3488,8 +3497,7 @@ fail_exit: ibuf_mtr_start(&bitmap_mtr); index->set_modified(bitmap_mtr); - bitmap_page = ibuf_bitmap_get_map_page(page_id, page_size, - &bitmap_mtr); + bitmap_page = ibuf_bitmap_get_map_page(page_id, zip_size, &bitmap_mtr); /* We check if the index page is suitable for buffered entries */ @@ -3503,11 +3511,12 @@ fail_exit: if (op == IBUF_OP_INSERT) { ulint bits = ibuf_bitmap_page_get_bits( - bitmap_page, page_id, page_size, IBUF_BITMAP_FREE, + bitmap_page, page_id, physical_size, IBUF_BITMAP_FREE, &bitmap_mtr); if (buffered + entry_size + page_dir_calc_reserved_space(1) - > ibuf_index_page_calc_free_from_bits(page_size, bits)) { + > ibuf_index_page_calc_free_from_bits(physical_size, + bits)) { /* Release the bitmap page latch early. */ ibuf_mtr_commit(&bitmap_mtr); @@ -3550,11 +3559,11 @@ fail_exit: buffered entries for this index page, if the bit is not set yet */ old_bit_value = ibuf_bitmap_page_get_bits( - bitmap_page, page_id, page_size, + bitmap_page, page_id, physical_size, IBUF_BITMAP_BUFFERED, &bitmap_mtr); if (!old_bit_value) { - ibuf_bitmap_page_set_bits(bitmap_page, page_id, page_size, + ibuf_bitmap_page_set_bits(bitmap_page, page_id, physical_size, IBUF_BITMAP_BUFFERED, TRUE, &bitmap_mtr); } @@ -3659,23 +3668,23 @@ func_exit: return(err); } -/** Buffer an operation in the insert/delete buffer, instead of doing it -directly to the disk page, if this is possible. Does not do it if the index +/** Buffer an operation in the change buffer, instead of applying it +directly to the file page, if this is possible. Does not do it if the index is clustered or unique. @param[in] op operation type @param[in] entry index entry to insert @param[in,out] index index where to insert @param[in] page_id page id where to insert -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] thr query thread -@return TRUE if success */ -ibool +@return true if success */ +bool ibuf_insert( ibuf_op_t op, const dtuple_t* entry, dict_index_t* index, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, que_thr_t* thr) { dberr_t err; @@ -3703,7 +3712,7 @@ ibuf_insert( case IBUF_USE_NONE: case IBUF_USE_DELETE: case IBUF_USE_DELETE_MARK: - DBUG_RETURN(FALSE); + DBUG_RETURN(false); case IBUF_USE_INSERT: case IBUF_USE_INSERT_DELETE_MARK: case IBUF_USE_ALL: @@ -3714,7 +3723,7 @@ ibuf_insert( switch (use) { case IBUF_USE_NONE: case IBUF_USE_INSERT: - DBUG_RETURN(FALSE); + DBUG_RETURN(false); case IBUF_USE_DELETE_MARK: case IBUF_USE_DELETE: case IBUF_USE_INSERT_DELETE_MARK: @@ -3728,7 +3737,7 @@ ibuf_insert( case IBUF_USE_NONE: case IBUF_USE_INSERT: case IBUF_USE_INSERT_DELETE_MARK: - DBUG_RETURN(FALSE); + DBUG_RETURN(false); case IBUF_USE_DELETE_MARK: case IBUF_USE_DELETE: case IBUF_USE_ALL: @@ -3768,7 +3777,7 @@ check_watch: is being buffered, have this request executed directly on the page in the buffer pool after the buffered entries for this page have been merged. */ - DBUG_RETURN(FALSE); + DBUG_RETURN(false); } } @@ -3779,30 +3788,22 @@ skip_watch: >= page_get_free_space_of_empty(dict_table_is_comp(index->table)) / 2) { - DBUG_RETURN(FALSE); + DBUG_RETURN(false); } err = ibuf_insert_low(BTR_MODIFY_PREV, op, no_counter, entry, entry_size, - index, page_id, page_size, thr); + index, page_id, zip_size, thr); if (err == DB_FAIL) { err = ibuf_insert_low(BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT, op, no_counter, entry, entry_size, - index, page_id, page_size, thr); + index, page_id, zip_size, thr); } - if (err == DB_SUCCESS) { -#ifdef UNIV_IBUF_DEBUG - /* fprintf(stderr, "Ibuf insert for page no %lu of index %s\n", - page_no, index->name); */ -#endif - DBUG_RETURN(TRUE); + ut_a(err == DB_SUCCESS || err == DB_STRONG_FAIL + || err == DB_TOO_BIG_RECORD); - } else { - ut_a(err == DB_STRONG_FAIL || err == DB_TOO_BIG_RECORD); - - DBUG_RETURN(FALSE); - } + DBUG_RETURN(err == DB_SUCCESS); } /********************************************************************//** @@ -3866,13 +3867,13 @@ ibuf_insert_to_index_page_low( "InnoDB: that table.\n", stderr); bitmap_page = ibuf_bitmap_get_map_page(block->page.id, - block->page.size, mtr); + block->zip_size(), mtr); old_bits = ibuf_bitmap_page_get_bits( - bitmap_page, block->page.id, block->page.size, + bitmap_page, block->page.id, block->zip_size(), IBUF_BITMAP_FREE, mtr); ib::error() << "page " << block->page.id << ", size " - << block->page.size.physical() << ", bitmap bits " << old_bits; + << block->physical_size() << ", bitmap bits " << old_bits; ib::error() << BUG_REPORT_MSG; @@ -4398,15 +4399,16 @@ subsequently was dropped. @param[in,out] block if page has been read from disk, pointer to the page x-latched, else NULL @param[in] page_id page id of the index page -@param[in] update_ibuf_bitmap normally this is set to TRUE, but +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in] update_ibuf_bitmap normally this is set, but if we have deleted or are deleting the tablespace, then we naturally do not want to update a non-existent bitmap page */ void ibuf_merge_or_delete_for_page( buf_block_t* block, const page_id_t page_id, - const page_size_t* page_size, - ibool update_ibuf_bitmap) + ulint zip_size, + bool update_ibuf_bitmap) { mem_heap_t* heap; btr_pcur_t pcur; @@ -4431,38 +4433,23 @@ ibuf_merge_or_delete_for_page( return; } - /* We cannot refer to page_size in the following, because it is passed - as NULL (it is unknown) when buf_read_ibuf_merge_pages() is merging - (discarding) changes for a dropped tablespace. When block != NULL or - update_ibuf_bitmap is specified, then page_size must be known. - That is why we will repeat the check below, with page_size in - place of univ_page_size. Passing univ_page_size assumes that the - uncompressed page size always is a power-of-2 multiple of the - compressed page size. */ + const ulint physical_size = zip_size ? zip_size : srv_page_size; - if (ibuf_fixed_addr_page(page_id, univ_page_size) - || fsp_descr_page(page_id, univ_page_size)) { + if (ibuf_fixed_addr_page(page_id, physical_size) + || fsp_descr_page(page_id, physical_size)) { return; } fil_space_t* space; if (update_ibuf_bitmap) { - - ut_ad(page_size != NULL); - - if (ibuf_fixed_addr_page(page_id, *page_size) - || fsp_descr_page(page_id, *page_size)) { - return; - } - space = fil_space_acquire_silent(page_id.space()); if (UNIV_UNLIKELY(!space)) { /* Do not try to read the bitmap page from the non-existent tablespace, delete the ibuf records */ block = NULL; - update_ibuf_bitmap = FALSE; + update_ibuf_bitmap = false; } else { page_t* bitmap_page = NULL; ulint bitmap_bits = 0; @@ -4470,12 +4457,12 @@ ibuf_merge_or_delete_for_page( ibuf_mtr_start(&mtr); bitmap_page = ibuf_bitmap_get_map_page( - page_id, *page_size, &mtr); + page_id, zip_size, &mtr); if (bitmap_page && fil_page_get_type(bitmap_page) != FIL_PAGE_TYPE_ALLOCATED) { bitmap_bits = ibuf_bitmap_page_get_bits( - bitmap_page, page_id, *page_size, + bitmap_page, page_id, zip_size, IBUF_BITMAP_BUFFERED, &mtr); } @@ -4489,8 +4476,8 @@ ibuf_merge_or_delete_for_page( } } } else if (block != NULL - && (ibuf_fixed_addr_page(page_id, *page_size) - || fsp_descr_page(page_id, *page_size))) { + && (ibuf_fixed_addr_page(page_id, physical_size) + || fsp_descr_page(page_id, physical_size))) { return; } else { @@ -4723,23 +4710,23 @@ reset_bit: if (update_ibuf_bitmap) { page_t* bitmap_page; - bitmap_page = ibuf_bitmap_get_map_page(page_id, *page_size, + bitmap_page = ibuf_bitmap_get_map_page(page_id, zip_size, &mtr); ibuf_bitmap_page_set_bits( - bitmap_page, page_id, *page_size, + bitmap_page, page_id, physical_size, IBUF_BITMAP_BUFFERED, FALSE, &mtr); if (block != NULL) { ulint old_bits = ibuf_bitmap_page_get_bits( - bitmap_page, page_id, *page_size, + bitmap_page, page_id, zip_size, IBUF_BITMAP_FREE, &mtr); ulint new_bits = ibuf_index_page_calc_free(block); if (old_bits != new_bits) { ibuf_bitmap_page_set_bits( - bitmap_page, page_id, *page_size, + bitmap_page, page_id, physical_size, IBUF_BITMAP_FREE, new_bits, &mtr); } } @@ -4922,9 +4909,9 @@ ibuf_print( @param[in] read_buf database page @param[in] size page size @return whether the page is all zeroes */ -static bool buf_page_is_zeroes(const byte* read_buf, const page_size_t& size) +static bool buf_page_is_zeroes(const byte* read_buf, ulint size) { - for (ulint i = 0; i < size.physical(); i++) { + for (ulint i = 0; i < size; i++) { if (read_buf[i] != 0) { return false; } @@ -4941,7 +4928,9 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) ulint page_no; ut_ad(trx->mysql_thd); ut_ad(space->purpose == FIL_TYPE_IMPORT); - const page_size_t page_size(space->flags); + + const ulint zip_size = space->zip_size(); + const ulint physical_size = space->physical_size(); /* fil_space_t::size and fil_space_t::free_limit would still be 0 at this point. So, we will have to read page 0. */ ut_ad(!space->free_limit); @@ -4950,7 +4939,8 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) mtr_t mtr; ulint size; mtr.start(); - if (buf_block_t* sp = buf_page_get(page_id_t(space->id, 0), page_size, + if (buf_block_t* sp = buf_page_get(page_id_t(space->id, 0), + zip_size, RW_S_LATCH, &mtr)) { size = std::min( mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT @@ -4974,7 +4964,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) below page_no is measured in number of pages since the beginning of the space, as usual. */ - for (page_no = 0; page_no < size; page_no += page_size.physical()) { + for (page_no = 0; page_no < size; page_no += physical_size) { page_t* bitmap_page; ulint i; @@ -4990,21 +4980,21 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) ibuf_enter(&mtr); bitmap_page = ibuf_bitmap_get_map_page( - page_id_t(space->id, page_no), page_size, &mtr); + page_id_t(space->id, page_no), zip_size, &mtr); - if (buf_page_is_zeroes(bitmap_page, page_size)) { + if (buf_page_is_zeroes(bitmap_page, physical_size)) { /* This means we got all-zero page instead of ibuf bitmap page. The subsequent page should be all-zero pages. */ #ifdef UNIV_DEBUG for (ulint curr_page = page_no + 1; - curr_page < page_size.physical(); curr_page++) { + curr_page < physical_size; curr_page++) { buf_block_t* block = buf_page_get( page_id_t(space->id, curr_page), - page_size, RW_S_LATCH, &mtr); + zip_size, RW_S_LATCH, &mtr); page_t* page = buf_block_get_frame(block); - ut_ad(buf_page_is_zeroes(page, page_size)); + ut_ad(buf_page_is_zeroes(page, physical_size)); } #endif /* UNIV_DEBUG */ ibuf_exit(&mtr); @@ -5017,17 +5007,13 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) return DB_CORRUPTION; } - for (i = FSP_IBUF_BITMAP_OFFSET + 1; - i < page_size.physical(); - i++) { - + for (i = FSP_IBUF_BITMAP_OFFSET + 1; i < physical_size; i++) { const ulint offset = page_no + i; - const page_id_t cur_page_id(space->id, offset); if (ibuf_bitmap_page_get_bits( - bitmap_page, cur_page_id, page_size, - IBUF_BITMAP_IBUF, &mtr)) { + bitmap_page, cur_page_id, zip_size, + IBUF_BITMAP_IBUF, &mtr)) { mutex_exit(&ibuf_mutex); ibuf_exit(&mtr); @@ -5044,7 +5030,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) } if (ibuf_bitmap_page_get_bits( - bitmap_page, cur_page_id, page_size, + bitmap_page, cur_page_id, zip_size, IBUF_BITMAP_BUFFERED, &mtr)) { ib_errf(trx->mysql_thd, @@ -5059,7 +5045,8 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space) slightly corrupted tables can be imported and dumped. Clear the bit. */ ibuf_bitmap_page_set_bits( - bitmap_page, cur_page_id, page_size, + bitmap_page, cur_page_id, + physical_size, IBUF_BITMAP_BUFFERED, FALSE, &mtr); } } @@ -5089,18 +5076,18 @@ ibuf_set_bitmap_for_bulk_load( free_val = ibuf_index_page_calc_free(block); mtr_start(&mtr); - mtr.set_named_space_id(block->page.id.space()); + fil_space_t* space = mtr.set_named_space_id(block->page.id.space()); bitmap_page = ibuf_bitmap_get_map_page(block->page.id, - block->page.size, &mtr); + space->zip_size(), &mtr); free_val = reset ? 0 : ibuf_index_page_calc_free(block); ibuf_bitmap_page_set_bits( - bitmap_page, block->page.id, block->page.size, + bitmap_page, block->page.id, block->physical_size(), IBUF_BITMAP_FREE, free_val, &mtr); ibuf_bitmap_page_set_bits( - bitmap_page, block->page.id, block->page.size, + bitmap_page, block->page.id, block->physical_size(), IBUF_BITMAP_BUFFERED, FALSE, &mtr); mtr_commit(&mtr); diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h index 42d7cb3d32b..5d8dd93d655 100644 --- a/storage/innobase/include/btr0btr.h +++ b/storage/innobase/include/btr0btr.h @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2014, 2018, MariaDB Corporation. +Copyright (c) 2014, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -219,6 +219,7 @@ btr_height_get( /** Gets a buffer page and declares its latching order level. @param[in] page_id page id +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] mode latch mode @param[in] file file name @param[in] line line where called @@ -230,7 +231,7 @@ UNIV_INLINE buf_block_t* btr_block_get_func( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint mode, const char* file, unsigned line, @@ -240,28 +241,28 @@ btr_block_get_func( # ifdef UNIV_DEBUG /** Gets a buffer page and declares its latching order level. @param page_id tablespace/page identifier -@param page_size page size +@param zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param mode latch mode @param index index tree, may be NULL if not the insert buffer tree @param mtr mini-transaction handle @return the block descriptor */ -# define btr_block_get(page_id, page_size, mode, index, mtr) \ - btr_block_get_func(page_id, page_size, mode, \ +# define btr_block_get(page_id, zip_size, mode, index, mtr) \ + btr_block_get_func(page_id, zip_size, mode, \ __FILE__, __LINE__, (dict_index_t*)index, mtr) # else /* UNIV_DEBUG */ /** Gets a buffer page and declares its latching order level. @param page_id tablespace/page identifier -@param page_size page size +@param zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param mode latch mode @param index index tree, may be NULL if not the insert buffer tree @param mtr mini-transaction handle @return the block descriptor */ -# define btr_block_get(page_id, page_size, mode, index, mtr) \ - btr_block_get_func(page_id, page_size, mode, __FILE__, __LINE__, (dict_index_t*)index, mtr) +# define btr_block_get(page_id, zip_size, mode, index, mtr) \ + btr_block_get_func(page_id, zip_size, mode, __FILE__, __LINE__, (dict_index_t*)index, mtr) # endif /* UNIV_DEBUG */ /** Gets a buffer page and declares its latching order level. @param page_id tablespace/page identifier -@param page_size page size +@param zip_size compressed page size in bytes or 0 for uncompressed pages @param mode latch mode @param index index tree, may be NULL if not the insert buffer tree @param mtr mini-transaction handle @@ -269,9 +270,8 @@ btr_block_get_func( UNIV_INLINE page_t* btr_page_get( -/*=========*/ const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint mode, dict_index_t* index, mtr_t* mtr) @@ -367,23 +367,19 @@ btr_create( /** Free a persistent index tree if it exists. @param[in] page_id root page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] index_id PAGE_INDEX_ID contents @param[in,out] mtr mini-transaction */ void btr_free_if_exists( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, index_id_t index_id, mtr_t* mtr); -/** Free an index tree in a temporary tablespace or during TRUNCATE TABLE. -@param[in] page_id root page id -@param[in] page_size page size */ -void -btr_free( - const page_id_t page_id, - const page_size_t& page_size); +/** Free an index tree in a temporary tablespace. +@param[in] page_id root page id */ +void btr_free(const page_id_t page_id); /** Read the last used AUTO_INCREMENT value from PAGE_ROOT_AUTO_INC. @param[in,out] index clustered index @@ -807,17 +803,20 @@ btr_validate_index( const trx_t* trx) /*!< in: transaction or 0 */ MY_ATTRIBUTE((warn_unused_result)); -/*************************************************************//** -Removes a page from the level list of pages. */ -UNIV_INTERN +/** Remove a page from the level list of pages. +@param[in] space space where removed +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in,out] page page to remove +@param[in] index index tree +@param[in,out] mtr mini-transaction */ void btr_level_list_remove_func( -/*=======================*/ - ulint space, /*!< in: space where removed */ - const page_size_t& page_size,/*!< in: page size */ - page_t* page, /*!< in/out: page to remove */ - dict_index_t* index, /*!< in: index tree */ - mtr_t* mtr); /*!< in/out: mini-transaction */ + ulint space, + ulint zip_size, + page_t* page, + dict_index_t* index, + mtr_t* mtr); + /*************************************************************//** Removes a page from the level list of pages. @param space in: space where removed diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic index 2669611a9e6..3cdf279f25f 100644 --- a/storage/innobase/include/btr0btr.ic +++ b/storage/innobase/include/btr0btr.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -31,6 +31,7 @@ Created 6/2/1994 Heikki Tuuri /** Gets a buffer page and declares its latching order level. @param[in] page_id page id +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] mode latch mode @param[in] file file name @param[in] line line where called @@ -42,7 +43,7 @@ UNIV_INLINE buf_block_t* btr_block_get_func( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint mode, const char* file, unsigned line, @@ -53,7 +54,7 @@ btr_block_get_func( dberr_t err=DB_SUCCESS; block = buf_page_get_gen( - page_id, page_size, mode, NULL, BUF_GET, file, line, mtr, &err); + page_id, zip_size, mode, NULL, BUF_GET, file, line, mtr, &err); if (err == DB_DECRYPTION_FAILED) { if (index && index->table) { @@ -96,7 +97,7 @@ btr_page_set_index_id( } /** Gets a buffer page and declares its latching order level. -@param space tablespace identifier +@param page_id tablespace/page identifier @param zip_size compressed page size in bytes or 0 for uncompressed pages @param page_no page number @param mode latch mode @@ -106,9 +107,8 @@ btr_page_set_index_id( UNIV_INLINE page_t* btr_page_get( -/*=========*/ const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint mode, dict_index_t* index, mtr_t* mtr) @@ -116,7 +116,7 @@ btr_page_get( buf_block_t* block=NULL; buf_frame_t* frame=NULL; - block = btr_block_get(page_id, page_size, mode, index, mtr); + block = btr_block_get(page_id, zip_size, mode, index, mtr); if (block) { frame = buf_block_get_frame(block); diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h index 358f394c5b4..44b679bd07b 100644 --- a/storage/innobase/include/btr0cur.h +++ b/storage/innobase/include/btr0cur.h @@ -723,11 +723,12 @@ btr_free_externally_stored_field( ignored if rec == NULL */ bool rollback, /*!< in: performing rollback? */ mtr_t* local_mtr); /*!< in: mtr containing the latch */ + /** Copies the prefix of an externally stored field of a record. The clustered index record must be protected by a lock or a page latch. @param[out] buf the field, or a prefix of it @param[in] len length of buf, in bytes -@param[in] page_size BLOB page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] data 'internally' stored part of the field containing also the reference to the external part; must be protected by a lock or a page latch @@ -738,7 +739,7 @@ ulint btr_copy_externally_stored_field_prefix( byte* buf, ulint len, - const page_size_t& page_size, + ulint zip_size, const byte* data, ulint local_len); @@ -748,7 +749,7 @@ The clustered index record must be protected by a lock or a page latch. @param[in] data 'internally' stored part of the field containing also the reference to the external part; must be protected by a lock or a page latch -@param[in] page_size BLOB page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] local_len length of data @param[in,out] heap mem heap @return the whole field copied to heap */ @@ -756,7 +757,7 @@ byte* btr_copy_externally_stored_field( ulint* len, const byte* data, - const page_size_t& page_size, + ulint zip_size, ulint local_len, mem_heap_t* heap); @@ -764,7 +765,7 @@ btr_copy_externally_stored_field( @param[in] rec record in a clustered index; must be protected by a lock or a page latch @param[in] offset array returned by rec_get_offsets() -@param[in] page_size BLOB page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] no field number @param[out] len length of the field @param[in,out] heap mem heap @@ -773,7 +774,7 @@ byte* btr_rec_copy_externally_stored_field( const rec_t* rec, const ulint* offsets, - const page_size_t& page_size, + ulint zip_size, ulint no, ulint* len, mem_heap_t* heap); @@ -816,6 +817,7 @@ btr_rec_set_deleted_flag( /** Latches the leaf page or pages requested. @param[in] block leaf page where the search converged @param[in] page_id page id of the leaf +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] latch_mode BTR_SEARCH_LEAF, ... @param[in] cursor cursor @param[in] mtr mini-transaction @@ -824,7 +826,7 @@ btr_latch_leaves_t btr_cur_latch_leaves( buf_block_t* block, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint latch_mode, btr_cur_t* cursor, mtr_t* mtr); diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h index fa59275dbff..0eb89f28de1 100644 --- a/storage/innobase/include/btr0types.h +++ b/storage/innobase/include/btr0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, MariaDB Corporation. +Copyright (c) 2018, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -28,7 +28,6 @@ Created 2/17/1996 Heikki Tuuri #define btr0types_h #include "page0types.h" -#include "page0size.h" #include "rem0types.h" /** Persistent cursor */ @@ -50,10 +49,17 @@ extern ulong btr_ahi_parts; /** The size of a reference to data stored on a different page. The reference is stored at the end of the prefix of the field in the index record. */ +#define FIELD_REF_SIZE 20U #define BTR_EXTERN_FIELD_REF_SIZE FIELD_REF_SIZE /** If the data don't exceed the size, the data are stored locally. */ #define BTR_EXTERN_LOCAL_STORED_MAX_SIZE \ (BTR_EXTERN_FIELD_REF_SIZE * 2) +/** A field reference full of zero, for use in assertions and checks, +and dummy default values of instantly dropped columns. +Initially, BLOB field references are set to zero, in +dtuple_convert_big_rec(). */ +extern const byte field_ref_zero[UNIV_PAGE_SIZE_MAX]; + #endif diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index e888cd64a0a..381b9f8f049 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -488,15 +488,13 @@ be implemented at a higher level. In other words, all possible accesses to a given page through this function must be protected by the same set of mutexes or latches. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size @return pointer to the block */ -buf_page_t* -buf_page_get_zip( - const page_id_t page_id, - const page_size_t& page_size); +buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size); /** This is the general function used to get access to a database page. @param[in] page_id page id +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH @param[in] guess guessed block or NULL @param[in] mode BUF_GET, BUF_GET_IF_IN_POOL, @@ -509,7 +507,7 @@ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or BUF_GET_IF_IN_POOL_OR_WATCH buf_block_t* buf_page_get_gen( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint rw_latch, buf_block_t* guess, ulint mode, @@ -518,18 +516,18 @@ buf_page_get_gen( mtr_t* mtr, dberr_t* err); -/** Initializes a page to the buffer buf_pool. The page is usually not read +/** Initialize a page in the buffer pool. The page is usually not read from a file even if it cannot be found in the buffer buf_pool. This is one of the functions which perform to a block a state transition NOT_USED => FILE_PAGE (the other is buf_page_get_gen). @param[in] page_id page id -@param[in] page_size page size -@param[in] mtr mini-transaction +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in,out] mtr mini-transaction @return pointer to the block, page bufferfixed */ buf_block_t* buf_page_create( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, mtr_t* mtr); /********************************************************************//** @@ -719,14 +717,14 @@ buf_page_is_checksum_valid_none( /** Check if a page is corrupt. @param[in] check_lsn whether the LSN should be checked @param[in] read_buf database page -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] space tablespace @return whether the page is corrupted */ bool buf_page_is_corrupted( bool check_lsn, const byte* read_buf, - const page_size_t& page_size, + ulint zip_size, #ifndef UNIV_INNOCHECKSUM const fil_space_t* space = NULL) #else @@ -795,10 +793,8 @@ buf_print(void); /** Dump a page to stderr. @param[in] read_buf database page -@param[in] page_size page size */ -UNIV_INTERN -void -buf_page_print(const byte* read_buf, const page_size_t& page_size) +@param[in] zip_size compressed page size, or 0 */ +void buf_page_print(const byte* read_buf, ulint zip_size = 0) ATTRIBUTE_COLD __attribute__((nonnull)); /********************************************************************//** Decompress a block. @@ -1157,6 +1153,7 @@ and the lock released later. @param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED @param[in] mode BUF_READ_IBUF_PAGES_ONLY, ... @param[in] page_id page id +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] unzip whether the uncompressed page is requested (for ROW_FORMAT=COMPRESSED) @return pointer to the block @@ -1166,7 +1163,7 @@ buf_page_init_for_read( dberr_t* err, ulint mode, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, bool unzip); /** Complete a read or write request of a file page to or from the buffer pool. @@ -1458,9 +1455,6 @@ public: buf_pool->page_hash or buf_pool->zip_hash */ - /** Page size. Protected by buf_pool mutex. */ - page_size_t size; - /** Count of how manyfold this block is currently bufferfixed. */ Atomic_counter buf_fix_count; @@ -1622,6 +1616,19 @@ public: ut_ad(count != 0); return count - 1; } + + /** @return the physical size, in bytes */ + ulint physical_size() const + { + return zip.ssize ? (UNIV_ZIP_SIZE_MIN >> 1) << zip.ssize : srv_page_size; + } + + /** @return the ROW_FORMAT=COMPRESSED physical size, in bytes + @retval 0 if not compressed */ + ulint zip_size() const + { + return zip.ssize ? (UNIV_ZIP_SIZE_MIN >> 1) << zip.ssize : 0; + } }; /** The buffer control block structure */ @@ -1788,6 +1795,13 @@ struct buf_block_t{ void fix() { page.fix(); } uint32_t unfix() { return page.unfix(); } + + /** @return the physical size, in bytes */ + ulint physical_size() const { return page.physical_size(); } + + /** @return the ROW_FORMAT=COMPRESSED physical size, in bytes + @retval 0 if not compressed */ + ulint zip_size() const { return page.zip_size(); } }; /** Check if a buf_block_t object is in a valid state diff --git a/storage/innobase/include/buf0rea.h b/storage/innobase/include/buf0rea.h index c32b0d3637e..057ce7711f5 100644 --- a/storage/innobase/include/buf0rea.h +++ b/storage/innobase/include/buf0rea.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -34,30 +34,23 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets an exclusive lock on the buffer frame. The flag is cleared and the x-lock released by the i/o-handler thread. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @retval DB_SUCCESS if the page was read and is not corrupted, @retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted, @retval DB_DECRYPTION_FAILED if page post encryption checksum matches but after decryption normal page checksum does not match. @retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */ -dberr_t -buf_read_page( - const page_id_t page_id, - const page_size_t& page_size); +dberr_t buf_read_page(const page_id_t page_id, ulint zip_size); -/********************************************************************//** -High-level function which reads a page asynchronously from a file to the +/** High-level function which reads a page asynchronously from a file to the buffer buf_pool if it is not already there. Sets the io_fix flag and sets an exclusive lock on the buffer frame. The flag is cleared and the x-lock released by the i/o-handler thread. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] sync true if synchronous aio is desired */ void -buf_read_page_background( - const page_id_t page_id, - const page_size_t& page_size, - bool sync); +buf_read_page_background(const page_id_t page_id, ulint zip_size, bool sync); /** Applies a random read-ahead in buf_pool if there are at least a threshold value of accessed pages from the random read-ahead area. Does not read any @@ -70,16 +63,13 @@ performed by ibuf routines, a situation which could result in a deadlock if the OS does not support asynchronous i/o. @param[in] page_id page id of a page which the current thread wants to access -@param[in] page_size page size -@param[in] inside_ibuf TRUE if we are inside ibuf routine +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in] ibuf whether we are inside ibuf routine @return number of page read requests issued; NOTE that if we read ibuf pages, it may happen that the page at the given page number does not get read even if we return a positive value! */ ulint -buf_read_ahead_random( - const page_id_t page_id, - const page_size_t& page_size, - ibool inside_ibuf); +buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf); /** Applies linear read-ahead if in the buf_pool the page is a border page of a linear read-ahead area and all the pages in the area have been accessed. @@ -104,14 +94,11 @@ NOTE 3: the calling thread must want access to the page given: this rule is set to prevent unintended read-aheads performed by ibuf routines, a situation which could result in a deadlock if the OS does not support asynchronous io. @param[in] page_id page id; see NOTE 3 above -@param[in] page_size page size -@param[in] inside_ibuf TRUE if we are inside ibuf routine +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in] ibuf whether if we are inside ibuf routine @return number of page read requests issued */ ulint -buf_read_ahead_linear( - const page_id_t page_id, - const page_size_t& page_size, - ibool inside_ibuf); +buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf); /********************************************************************//** Issues read requests for pages which the ibuf module wants to read in, in diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index e602a81ed27..202d56365b7 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -887,25 +887,33 @@ ulint dict_tf_to_fsp_flags(ulint table_flags) MY_ATTRIBUTE((const)); -/** Extract the page size from table flags. + +/** Extract the ROW_FORMAT=COMPRESSED page size from table flags. @param[in] flags flags -@return compressed page size, or 0 if not compressed */ -UNIV_INLINE -const page_size_t -dict_tf_get_page_size( - ulint flags) -MY_ATTRIBUTE((const)); +@return ROW_FORMAT=COMPRESSED page size +@retval 0 if not compressed */ +inline ulint dict_tf_get_zip_size(ulint flags) +{ + flags &= DICT_TF_MASK_ZIP_SSIZE; + return flags + ? (UNIV_ZIP_SIZE_MIN >> 1) + << (FSP_FLAGS_GET_ZIP_SSIZE(flags >> DICT_TF_POS_ZIP_SSIZE + << FSP_FLAGS_POS_ZIP_SSIZE)) + : 0; +} /** Determine the extent size (in pages) for the given table @param[in] table the table whose extent size is being calculated. @return extent size in pages (256, 128 or 64) */ -ulint -dict_table_extent_size( - const dict_table_t* table); +inline ulint dict_table_extent_size(const dict_table_t* table) +{ + if (ulint zip_size = table->space->zip_size()) { + return (1ULL << 20) / zip_size; + } -/** Get the table page size. */ -#define dict_table_page_size(table) page_size_t(table->space->flags) + return FSP_EXTENT_SIZE; +} /*********************************************************************//** Obtain exclusive locks on all index trees of the table. This is to prevent diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index b970eaf0861..e0824469606 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -711,28 +711,6 @@ dict_tf_to_sys_tables_type( return(type); } -/** Extract the page size info from table flags. -@param[in] flags flags -@return a structure containing the compressed and uncompressed -page sizes and a boolean indicating if the page is compressed. */ -UNIV_INLINE -const page_size_t -dict_tf_get_page_size( - ulint flags) -{ - const ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags); - - if (zip_ssize == 0) { - return(univ_page_size); - } - - const ulint zip_size = (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize; - - ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX); - - return(page_size_t(zip_size, srv_page_size, true)); -} - /*********************************************************************//** Obtain exclusive locks on all index trees of the table. This is to prevent accessing index trees while InnoDB is updating internal metadata for diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h index e520f189d63..f278aa8fecb 100644 --- a/storage/innobase/include/fil0crypt.h +++ b/storage/innobase/include/fil0crypt.h @@ -1,6 +1,6 @@ /***************************************************************************** Copyright (C) 2013, 2015, Google Inc. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -273,13 +273,11 @@ fil_space_merge_crypt_data( const fil_space_crypt_t* src); /** Initialize encryption parameters from a tablespace header page. -@param[in] page_size page size of the tablespace +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] page first page of the tablespace @return crypt data from page 0 @retval NULL if not present or not valid */ -UNIV_INTERN -fil_space_crypt_t* -fil_space_read_crypt_data(const page_size_t& page_size, const byte* page) +fil_space_crypt_t* fil_space_read_crypt_data(ulint zip_size, const byte* page) MY_ATTRIBUTE((nonnull, warn_unused_result)); /** @@ -310,9 +308,10 @@ fil_parse_write_crypt_data( @param[in] offset Page offset @param[in] lsn Log sequence number @param[in] src_frame Page to encrypt -@param[in] page_size Page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] dst_frame Output buffer @return encrypted buffer or NULL */ +UNIV_INTERN byte* fil_encrypt_buf( fil_space_crypt_t* crypt_data, @@ -320,7 +319,7 @@ fil_encrypt_buf( ulint offset, lsn_t lsn, const byte* src_frame, - const page_size_t& page_size, + ulint zip_size, byte* dst_frame) MY_ATTRIBUTE((warn_unused_result)); @@ -343,20 +342,20 @@ fil_space_encrypt( byte* dst_frame) MY_ATTRIBUTE((warn_unused_result)); -/** -Decrypt a page. -@param[in,out] crypt_data crypt_data + +/** Decrypt a page. +@param[in] crypt_data crypt_data @param[in] tmp_frame Temporary buffer -@param[in] page_size Page size +@param[in] physical_size page size @param[in,out] src_frame Page to decrypt -@param[out] err DB_SUCCESS or error +@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED @return true if page decrypted, false if not.*/ UNIV_INTERN bool fil_space_decrypt( fil_space_crypt_t* crypt_data, byte* tmp_frame, - const page_size_t& page_size, + ulint physical_size, byte* src_frame, dberr_t* err); @@ -377,17 +376,14 @@ fil_space_decrypt( bool* decrypted) MY_ATTRIBUTE((warn_unused_result)); -/****************************************************************** +/** Calculate post encryption checksum -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] dst_frame Block where checksum is calculated -@return page checksum or BUF_NO_CHECKSUM_MAGIC +@return page checksum not needed. */ -UNIV_INTERN uint32_t -fil_crypt_calculate_checksum( - const page_size_t& page_size, - const byte* dst_frame) +fil_crypt_calculate_checksum(ulint zip_size, const byte* dst_frame) MY_ATTRIBUTE((warn_unused_result)); /********************************************************************* @@ -485,10 +481,9 @@ calculated checksum as if it does page could be valid unencrypted, encrypted, or corrupted. @param[in,out] page page frame (checksum is temporarily modified) -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @return true if page is encrypted AND OK, false otherwise */ -bool -fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size) +bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size) MY_ATTRIBUTE((warn_unused_result)); #endif /* fil0crypt_h */ diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index c7278368368..5f17de80ab3 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -27,7 +27,7 @@ Created 10/25/1995 Heikki Tuuri #ifndef fil0fil_h #define fil0fil_h -#include "page0size.h" +#include "fsp0types.h" #ifndef UNIV_INNOCHECKSUM @@ -120,8 +120,7 @@ struct fil_space_t { or if the size change was implemented */ ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags; see fsp0types.h, - fsp_flags_is_valid(), - page_size_t(ulint) (constructor) */ + fsp_flags_is_valid() */ ulint n_reserved_extents; /*!< number of reserved free extents for ongoing operations like B-tree page split */ @@ -256,6 +255,44 @@ struct fil_space_t { void release_for_io() { ut_ad(pending_io()); n_pending_ios--; } /** @return whether I/O is pending */ bool pending_io() const { return n_pending_ios; } + + /** Determine the logical page size. + @param flags tablespace flags (FSP_FLAGS) + @return the logical page size + @retval 0 if the flags are invalid */ + static ulint logical_size(ulint flags) { + switch (FSP_FLAGS_GET_PAGE_SSIZE(flags)) { + case 3: return 4096; + case 4: return 8192; + case 0: return 16384; + case 6: return 32768; + case 7: return 65536; + default: return 0; + } + } + /** Determine the ROW_FORMAT=COMPRESSED page size. + @param flags tablespace flags (FSP_FLAGS) + @return the ROW_FORMAT=COMPRESSED page size + @retval 0 if ROW_FORMAT=COMPRESSED is not used */ + static ulint zip_size(ulint flags) { + ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); + return zip_ssize + ? (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize : 0; + } + /** Determine the physical page size. + @param flags tablespace flags (FSP_FLAGS) + @return the physical page size */ + static ulint physical_size(ulint flags) { + ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags); + return zip_ssize + ? (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize + : srv_page_size; + } + /** @return the ROW_FORMAT=COMPRESSED page size + @retval 0 if ROW_FORMAT=COMPRESSED is not used */ + ulint zip_size() const { return zip_size(flags); } + /** @return the physical page size */ + ulint physical_size() const { return physical_size(flags); } }; /** Value of fil_space_t::magic_n */ @@ -688,16 +725,6 @@ fil_space_get_flags( /*================*/ ulint id); /*!< in: space id */ -/** Returns the page size of the space and whether it is compressed or not. -The tablespace must be cached in the memory cache. -@param[in] id space id -@param[out] found true if tablespace was found -@return page size */ -const page_size_t -fil_space_get_page_size( - ulint id, - bool* found); - /*******************************************************************//** Opens all log files and system tablespace data files. They stay open until the database server shutdown. This should be called at a server startup after the @@ -1033,7 +1060,7 @@ fil_space_extend( @param[in] type IO context @param[in] sync true if synchronous aio is desired @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] byte_offset remainder of offset in bytes; in aio this must be divisible by the OS block size @param[in] len how many bytes to read or write; this must @@ -1052,7 +1079,7 @@ fil_io( const IORequest& type, bool sync, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, ulint byte_offset, ulint len, void* buf, diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 9b502f1f546..38ffc9bf4ae 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -201,11 +201,6 @@ typedef byte fseg_inode_t; (16 + 3 * FLST_BASE_NODE_SIZE \ + FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE) -#define FSP_SEG_INODES_PER_PAGE(page_size) \ - ((page_size.physical() - FSEG_ARR_OFFSET - 10) / FSEG_INODE_SIZE) - /* Number of segment inodes which fit on a - single page */ - #define FSEG_MAGIC_N_VALUE 97937874 #define FSEG_FILLFACTOR 8 /* If this value is x, then if @@ -290,33 +285,6 @@ the extent are free and which contain old tuple version to clean. */ #ifndef UNIV_INNOCHECKSUM /* @} */ -/** Calculate the number of pages to extend a datafile. -We extend single-table tablespaces first one extent at a time, -but 4 at a time for bigger tablespaces. It is not enough to extend always -by one extent, because we need to add at least one extent to FSP_FREE. -A single extent descriptor page will track many extents. And the extent -that uses its extent descriptor page is put onto the FSP_FREE_FRAG list. -Extents that do not use their extent descriptor page are added to FSP_FREE. -The physical page size is used to determine how many extents are tracked -on one extent descriptor page. See xdes_calc_descriptor_page(). -@param[in] page_size page_size of the datafile -@param[in] size current number of pages in the datafile -@return number of pages to extend the file. */ -ulint -fsp_get_pages_to_extend_ibd( - const page_size_t& page_size, - ulint size); - -/** Calculate the number of physical pages in an extent for this file. -@param[in] page_size page_size of the datafile -@return number of pages in an extent for this file. */ -UNIV_INLINE -ulint -fsp_get_extent_size_in_pages(const page_size_t& page_size) -{ - return (FSP_EXTENT_SIZE << srv_page_size_shift) / page_size.physical(); -} - /**********************************************************************//** Reads the space id from the first page of a tablespace. @return space id, ULINT UNDEFINED if error */ @@ -347,13 +315,15 @@ fsp_header_get_flags(const page_t* page) } /** Get the byte offset of encryption information in page 0. -@param[in] ps page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @return byte offset relative to FSP_HEADER_OFFSET */ inline MY_ATTRIBUTE((pure, warn_unused_result)) -ulint -fsp_header_get_encryption_offset(const page_size_t& ps) +ulint fsp_header_get_encryption_offset(ulint zip_size) { - return XDES_ARR_OFFSET + XDES_SIZE * ps.physical() / FSP_EXTENT_SIZE; + return zip_size + ? XDES_ARR_OFFSET + XDES_SIZE * zip_size / FSP_EXTENT_SIZE + : XDES_ARR_OFFSET + (XDES_SIZE << srv_page_size_shift) + / FSP_EXTENT_SIZE; } /** Check the encryption key from the first page of a tablespace. @@ -619,13 +589,12 @@ fil_block_check_type( /** Checks if a page address is an extent descriptor page address. @param[in] page_id page id -@param[in] page_size page size -@return TRUE if a descriptor page */ -UNIV_INLINE -ibool -fsp_descr_page( - const page_id_t page_id, - const page_size_t& page_size); +@param[in] physical_size page size +@return whether a descriptor page */ +inline bool fsp_descr_page(const page_id_t page_id, ulint physical_size) +{ + return (page_id.page_no() & (physical_size - 1)) == FSP_XDES_OFFSET; +} /***********************************************************//** Parses a redo log record of a file page init. @@ -776,16 +745,6 @@ fsp_flags_match(ulint expected, ulint actual) return(actual == expected); } -/** Calculates the descriptor index within a descriptor page. -@param[in] page_size page size -@param[in] offset page offset -@return descriptor index */ -UNIV_INLINE -ulint -xdes_calc_descriptor_index( - const page_size_t& page_size, - ulint offset); - /**********************************************************************//** Gets a descriptor bit of a page. @return TRUE if free */ @@ -798,15 +757,40 @@ xdes_get_bit( ulint offset);/*!< in: page offset within extent: 0 ... FSP_EXTENT_SIZE - 1 */ -/** Calculates the page where the descriptor of a page resides. -@param[in] page_size page size +/** Determine the descriptor index within a descriptor page. +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in] offset page offset +@return descriptor index */ +inline ulint xdes_calc_descriptor_index(ulint zip_size, ulint offset) +{ + return(ut_2pow_remainder(offset, zip_size ? zip_size : srv_page_size) + / FSP_EXTENT_SIZE); +} + +/** Determine the descriptor page number for a page. +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] offset page offset @return descriptor page offset */ -UNIV_INLINE -ulint -xdes_calc_descriptor_page( - const page_size_t& page_size, - ulint offset); +inline ulint xdes_calc_descriptor_page(ulint zip_size, ulint offset) +{ + compile_time_assert(UNIV_PAGE_SIZE_MAX > XDES_ARR_OFFSET + + (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX) + * XDES_SIZE_MAX); + compile_time_assert(UNIV_PAGE_SIZE_MIN > XDES_ARR_OFFSET + + (UNIV_PAGE_SIZE_MIN / FSP_EXTENT_SIZE_MIN) + * XDES_SIZE_MIN); + + ut_ad(srv_page_size > XDES_ARR_OFFSET + + (srv_page_size / FSP_EXTENT_SIZE) + * XDES_SIZE); + ut_ad(UNIV_ZIP_SIZE_MIN > XDES_ARR_OFFSET + + (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE) + * XDES_SIZE); + ut_ad(!zip_size + || zip_size > XDES_ARR_OFFSET + + (zip_size / FSP_EXTENT_SIZE) * XDES_SIZE); + return ut_2pow_round(offset, zip_size ? zip_size : srv_page_size); +} #endif /* UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic index 3258704615a..5977a954aea 100644 --- a/storage/innobase/include/fsp0fsp.ic +++ b/storage/innobase/include/fsp0fsp.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,37 +24,6 @@ File space management Created 12/18/1995 Heikki Tuuri *******************************************************/ -#ifndef UNIV_INNOCHECKSUM - -/** Checks if a page address is an extent descriptor page address. -@param[in] page_id page id -@param[in] page_size page size -@return TRUE if a descriptor page */ -UNIV_INLINE -ibool -fsp_descr_page( - const page_id_t page_id, - const page_size_t& page_size) -{ - return((page_id.page_no() & (page_size.physical() - 1)) - == FSP_XDES_OFFSET); -} - -/** Calculates the descriptor index within a descriptor page. -@param[in] page_size page size -@param[in] offset page offset -@return descriptor index */ -UNIV_INLINE -ulint -xdes_calc_descriptor_index( - const page_size_t& page_size, - ulint offset) -{ - return(ut_2pow_remainder(offset, page_size.physical()) - / FSP_EXTENT_SIZE); -} -#endif /*!UNIV_INNOCHECKSUM */ - /**********************************************************************//** Gets a descriptor bit of a page. @return TRUE if free */ @@ -80,39 +49,3 @@ xdes_get_bit( MLOG_1BYTE), bit_index)); } - -#ifndef UNIV_INNOCHECKSUM -/** Calculates the page where the descriptor of a page resides. -@param[in] page_size page size -@param[in] offset page offset -@return descriptor page offset */ -UNIV_INLINE -ulint -xdes_calc_descriptor_page( - const page_size_t& page_size, - ulint offset) -{ - compile_time_assert(UNIV_PAGE_SIZE_MAX > XDES_ARR_OFFSET - + (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX) - * XDES_SIZE_MAX); - compile_time_assert(UNIV_PAGE_SIZE_MIN > XDES_ARR_OFFSET - + (UNIV_PAGE_SIZE_MIN / FSP_EXTENT_SIZE_MIN) - * XDES_SIZE_MIN); - - ut_ad(srv_page_size > XDES_ARR_OFFSET - + (srv_page_size / FSP_EXTENT_SIZE) - * XDES_SIZE); - ut_ad(UNIV_ZIP_SIZE_MIN > XDES_ARR_OFFSET - + (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE) - * XDES_SIZE); - -#ifdef UNIV_DEBUG - if (page_size.is_compressed()) { - ut_a(page_size.physical() > XDES_ARR_OFFSET - + (page_size.physical() / FSP_EXTENT_SIZE) * XDES_SIZE); - } -#endif /* UNIV_DEBUG */ - - return(ut_2pow_round(offset, page_size.physical())); -} -#endif /* !UNIV_INNOCHECKSUM */ diff --git a/storage/innobase/include/fut0fut.h b/storage/innobase/include/fut0fut.h index d8072708089..e06fc3c5e92 100644 --- a/storage/innobase/include/fut0fut.h +++ b/storage/innobase/include/fut0fut.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -31,7 +32,7 @@ Created 12/13/1995 Heikki Tuuri /** Gets a pointer to a file address and latches the page. @param[in] space space id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] addr file address @param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_SX_LATCH @param[out] ptr_block file page @@ -42,13 +43,32 @@ UNIV_INLINE byte* fut_get_ptr( ulint space, - const page_size_t& page_size, + ulint zip_size, fil_addr_t addr, rw_lock_type_t rw_latch, mtr_t* mtr, buf_block_t** ptr_block = NULL) - MY_ATTRIBUTE((warn_unused_result)); +{ + buf_block_t* block; + byte* ptr = NULL; -#include "fut0fut.ic" + ut_ad(addr.boffset < srv_page_size); + ut_ad((rw_latch == RW_S_LATCH) + || (rw_latch == RW_X_LATCH) + || (rw_latch == RW_SX_LATCH)); + + block = buf_page_get(page_id_t(space, addr.page), zip_size, + rw_latch, mtr); + + ptr = buf_block_get_frame(block) + addr.boffset; + + buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); + + if (ptr_block != NULL) { + *ptr_block = block; + } + + return(ptr); +} #endif /* fut0fut_h */ diff --git a/storage/innobase/include/fut0fut.ic b/storage/innobase/include/fut0fut.ic deleted file mode 100644 index 56be971f233..00000000000 --- a/storage/innobase/include/fut0fut.ic +++ /dev/null @@ -1,68 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/******************************************************************//** -@file include/fut0fut.ic -File-based utilities - -Created 12/13/1995 Heikki Tuuri -***********************************************************************/ - -#include "sync0rw.h" -#include "buf0buf.h" - -/** Gets a pointer to a file address and latches the page. -@param[in] space space id -@param[in] page_size page size -@param[in] addr file address -@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_SX_LATCH -@param[in,out] mtr mini-transaction -@param[out] ptr_block file page -@return pointer to a byte in (*ptr_block)->frame; the *ptr_block is -bufferfixed and latched */ -UNIV_INLINE -byte* -fut_get_ptr( - ulint space, - const page_size_t& page_size, - fil_addr_t addr, - rw_lock_type_t rw_latch, - mtr_t* mtr, - buf_block_t** ptr_block) -{ - buf_block_t* block; - byte* ptr = NULL; - - ut_ad(addr.boffset < srv_page_size); - ut_ad((rw_latch == RW_S_LATCH) - || (rw_latch == RW_X_LATCH) - || (rw_latch == RW_SX_LATCH)); - - block = buf_page_get(page_id_t(space, addr.page), page_size, - rw_latch, mtr); - - ptr = buf_block_get_frame(block) + addr.boffset; - - buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); - - if (ptr_block != NULL) { - *ptr_block = block; - } - - return(ptr); -} diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 72b9e291fca..595ce5a8fed 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2018, MariaDB Corporation. +Copyright (c) 2016, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -241,18 +241,19 @@ ibuf_inside( /** Checks if a page address is an ibuf bitmap page (level 3 page) address. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @return TRUE if a bitmap page */ -UNIV_INLINE -ibool -ibuf_bitmap_page( - const page_id_t page_id, - const page_size_t& page_size); +inline bool ibuf_bitmap_page(const page_id_t page_id, ulint zip_size) +{ + ut_ad(ut_is_2pow(zip_size)); + ulint size = zip_size ? zip_size : srv_page_size; + return (page_id.page_no() & (size - 1)) == FSP_IBUF_BITMAP_OFFSET; +} /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. Must not be called when recv_no_ibuf_operations==true. @param[in] page_id page id -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] x_latch FALSE if relaxed check (avoid latching the bitmap page) @param[in] file file name @@ -260,13 +261,13 @@ bitmap page) @param[in,out] mtr mtr which will contain an x-latch to the bitmap page if the page is not one of the fixed address ibuf pages, or NULL, in which case a new transaction is created. -@return TRUE if level 2 or level 3 page */ -ibool +@return true if level 2 or level 3 page */ +bool ibuf_page_low( const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, #ifdef UNIV_DEBUG - ibool x_latch, + bool x_latch, #endif /* UNIV_DEBUG */ const char* file, unsigned line, @@ -278,22 +279,22 @@ ibuf_page_low( /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. Must not be called when recv_no_ibuf_operations==true. @param[in] page_id tablespace/page identifier -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] mtr mini-transaction or NULL @return TRUE if level 2 or level 3 page */ -# define ibuf_page(page_id, page_size, mtr) \ - ibuf_page_low(page_id, page_size, TRUE, __FILE__, __LINE__, mtr) +# define ibuf_page(page_id, zip_size, mtr) \ + ibuf_page_low(page_id, zip_size, true, __FILE__, __LINE__, mtr) #else /* UVIV_DEBUG */ /** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages. Must not be called when recv_no_ibuf_operations==true. @param[in] page_id tablespace/page identifier -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] mtr mini-transaction or NULL @return TRUE if level 2 or level 3 page */ -# define ibuf_page(page_id, page_size, mtr) \ - ibuf_page_low(page_id, page_size, __FILE__, __LINE__, mtr) +# define ibuf_page(page_id, zip_size, mtr) \ + ibuf_page_low(page_id, zip_size, __FILE__, __LINE__, mtr) #endif /* UVIV_DEBUG */ /***********************************************************************//** @@ -304,23 +305,23 @@ void ibuf_free_excess_pages(void); /*========================*/ -/** Buffer an operation in the insert/delete buffer, instead of doing it -directly to the disk page, if this is possible. Does not do it if the index +/** Buffer an operation in the change buffer, instead of applying it +directly to the file page, if this is possible. Does not do it if the index is clustered or unique. @param[in] op operation type @param[in] entry index entry to insert @param[in,out] index index where to insert @param[in] page_id page id where to insert -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] thr query thread -@return TRUE if success */ -ibool +@return true if success */ +bool ibuf_insert( ibuf_op_t op, const dtuple_t* entry, dict_index_t* index, const page_id_t page_id, - const page_size_t& page_size, + ulint zip_size, que_thr_t* thr); /** When an index page is read from a disk to the buffer pool, this function @@ -332,15 +333,16 @@ subsequently was dropped. @param[in,out] block if page has been read from disk, pointer to the page x-latched, else NULL @param[in] page_id page id of the index page -@param[in] update_ibuf_bitmap normally this is set to TRUE, but +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@param[in] update_ibuf_bitmap normally this is set, but if we have deleted or are deleting the tablespace, then we naturally do not want to update a non-existent bitmap page */ void ibuf_merge_or_delete_for_page( buf_block_t* block, const page_id_t page_id, - const page_size_t* page_size, - ibool update_ibuf_bitmap); + ulint zip_size, + bool update_ibuf_bitmap); /*********************************************************************//** Deletes all entries in the insert buffer for a given space id. This is used diff --git a/storage/innobase/include/ibuf0ibuf.ic b/storage/innobase/include/ibuf0ibuf.ic index e35b8a252a7..5be9569290b 100644 --- a/storage/innobase/include/ibuf0ibuf.ic +++ b/storage/innobase/include/ibuf0ibuf.ic @@ -150,20 +150,6 @@ ibuf_inside( return(mtr->is_inside_ibuf()); } -/** Checks if a page address is an ibuf bitmap page (level 3 page) address. -@param[in] page_id page id -@param[in] page_size page size -@return TRUE if a bitmap page */ -UNIV_INLINE -ibool -ibuf_bitmap_page( - const page_id_t page_id, - const page_size_t& page_size) -{ - return((page_id.page_no() & (page_size.physical() - 1)) - == FSP_IBUF_BITMAP_OFFSET); -} - /** Translates the free space on a page to a value in the ibuf bitmap. @param[in] page_size page size in bytes @param[in] max_ins_size maximum insert size after reorganize for @@ -192,29 +178,6 @@ ibuf_index_page_calc_free_bits( return(n); } -/** Translates the ibuf free bits to the free space on a page in bytes. -@param[in] page_size page_size -@param[in] bits value for ibuf bitmap bits -@return maximum insert size after reorganize for the page */ -UNIV_INLINE -ulint -ibuf_index_page_calc_free_from_bits( - const page_size_t& page_size, - ulint bits) -{ - ut_ad(bits < 4); - ut_ad(!page_size.is_compressed() - || page_size.physical() > IBUF_PAGE_SIZE_PER_FREE_SPACE); - - if (bits == 3) { - return(4 * page_size.physical() - / IBUF_PAGE_SIZE_PER_FREE_SPACE); - } - - return(bits * (page_size.physical() - / IBUF_PAGE_SIZE_PER_FREE_SPACE)); -} - /*********************************************************************//** Translates the free space on a compressed page to a value in the ibuf bitmap. @return value for ibuf bitmap bits */ @@ -228,7 +191,7 @@ ibuf_index_page_calc_free_zip( const page_zip_des_t* page_zip; lint zip_max_ins; - ut_ad(block->page.size.is_compressed()); + ut_ad(block->page.zip.data); /* Consider the maximum insert size on the uncompressed page without reorganizing the page. We must not assume anything @@ -251,7 +214,7 @@ ibuf_index_page_calc_free_zip( max_ins_size = (ulint) zip_max_ins; } - return(ibuf_index_page_calc_free_bits(block->page.size.physical(), + return(ibuf_index_page_calc_free_bits(block->physical_size(), max_ins_size)); } @@ -264,14 +227,14 @@ ibuf_index_page_calc_free( /*======================*/ const buf_block_t* block) /*!< in: buffer block */ { - if (!block->page.size.is_compressed()) { + if (!block->page.zip.data) { ulint max_ins_size; max_ins_size = page_get_max_insert_size_after_reorganize( buf_block_get_frame(block), 1); return(ibuf_index_page_calc_free_bits( - block->page.size.physical(), max_ins_size)); + block->physical_size(), max_ins_size)); } else { return(ibuf_index_page_calc_free_zip(block)); } @@ -312,12 +275,12 @@ ibuf_update_free_bits_if_full( ut_ad(buf_block_get_page_zip(block) == NULL); before = ibuf_index_page_calc_free_bits( - block->page.size.physical(), max_ins_size); + srv_page_size, max_ins_size); if (max_ins_size >= increase) { compile_time_assert(ULINT32_UNDEFINED > UNIV_PAGE_SIZE_MAX); after = ibuf_index_page_calc_free_bits( - block->page.size.physical(), max_ins_size - increase); + srv_page_size, max_ins_size - increase); #ifdef UNIV_IBUF_DEBUG ut_a(after <= ibuf_index_page_calc_free(block)); #endif diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic index 8a8d141ce11..bfe3a3afd51 100644 --- a/storage/innobase/include/mem0mem.ic +++ b/storage/innobase/include/mem0mem.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -212,7 +212,7 @@ mem_heap_alloc( mem_block_set_free(block, free + MEM_SPACE_NEEDED(n)); - UNIV_MEM_ALLOC(buf, n); + TRASH_ALLOC(buf, n); return(buf); } diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index 71da751ad25..2c11e447952 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -36,7 +36,7 @@ Created 10/21/1995 Heikki Tuuri #ifndef os0file_h #define os0file_h -#include "page0size.h" +#include "fsp0types.h" #include "os0api.h" #ifndef _WIN32 diff --git a/storage/innobase/include/page0size.h b/storage/innobase/include/page0size.h deleted file mode 100644 index 08d072822bf..00000000000 --- a/storage/innobase/include/page0size.h +++ /dev/null @@ -1,197 +0,0 @@ -/***************************************************************************** - -Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; version 2 of the License. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA - -*****************************************************************************/ - -/**************************************************//** -@file include/page0size.h -A class describing a page size. - -Created Nov 14, 2013 Vasil Dimov -*******************************************************/ - -#ifndef page0size_t -#define page0size_t - -#include "fsp0types.h" - -#define FIELD_REF_SIZE 20U - -/** A BLOB field reference full of zero, for use in assertions and -tests.Initially, BLOB field references are set to zero, in -dtuple_convert_big_rec(). */ -extern const byte field_ref_zero[UNIV_PAGE_SIZE_MAX]; - -#define PAGE_SIZE_T_SIZE_BITS 17 - -/** Page size descriptor. Contains the physical and logical page size, as well -as whether the page is compressed or not. */ -class page_size_t { -public: - /** Constructor from (physical, logical, is_compressed). - @param[in] physical physical (on-disk/zipped) page size - @param[in] logical logical (in-memory/unzipped) page size - @param[in] is_compressed whether the page is compressed */ - page_size_t(ulint physical, ulint logical, bool is_compressed) - { - if (physical == 0) { - physical = UNIV_PAGE_SIZE_ORIG; - } - if (logical == 0) { - logical = UNIV_PAGE_SIZE_ORIG; - } - - m_physical = static_cast(physical); - m_logical = static_cast(logical); - m_is_compressed = static_cast(is_compressed); - - ut_ad(physical <= (1 << PAGE_SIZE_T_SIZE_BITS)); - ut_ad(logical <= (1 << PAGE_SIZE_T_SIZE_BITS)); - - ut_ad(ut_is_2pow(physical)); - ut_ad(ut_is_2pow(logical)); - - ut_ad(logical <= UNIV_PAGE_SIZE_MAX); - ut_ad(logical >= physical); - ut_ad(!is_compressed || physical <= UNIV_ZIP_SIZE_MAX); - } - - /** Constructor from (fsp_flags). - @param[in] fsp_flags filespace flags */ - explicit page_size_t(ulint fsp_flags) - { - ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(fsp_flags); - - /* If the logical page size is zero in fsp_flags, then use the - legacy 16k page size. */ - ssize = (0 == ssize) ? UNIV_PAGE_SSIZE_ORIG : ssize; - - /* Convert from a 'log2 minus 9' to a page size in bytes. */ - const unsigned size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize); - - ut_ad(size <= UNIV_PAGE_SIZE_MAX); - ut_ad(size <= (1 << PAGE_SIZE_T_SIZE_BITS)); - - m_logical = size; - - ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags); - - /* If the fsp_flags have zero in the zip_ssize field, then it means - that the tablespace does not have compressed pages and the physical - page size is the same as the logical page size. */ - if (ssize == 0) { - m_is_compressed = false; - m_physical = m_logical; - } else { - m_is_compressed = true; - - /* Convert from a 'log2 minus 9' to a page size - in bytes. */ - const unsigned phy - = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize); - - ut_ad(phy <= UNIV_ZIP_SIZE_MAX); - ut_ad(phy <= (1 << PAGE_SIZE_T_SIZE_BITS)); - - m_physical = phy; - } - } - - /** Retrieve the physical page size (on-disk). - @return physical page size in bytes */ - inline ulint physical() const - { - ut_ad(m_physical > 0); - - return(m_physical); - } - - /** Retrieve the logical page size (in-memory). - @return logical page size in bytes */ - inline ulint logical() const - { - ut_ad(m_logical > 0); - return(m_logical); - } - - /** Check whether the page is compressed on disk. - @return true if compressed */ - inline bool is_compressed() const - { - return(m_is_compressed); - } - - /** Copy the values from a given page_size_t object. - @param[in] src page size object whose values to fetch */ - inline void copy_from(const page_size_t& src) - { - *this = src; - } - - /** Check if a given page_size_t object is equal to the current one. - @param[in] a page_size_t object to compare - @return true if equal */ - inline bool equals_to(const page_size_t& a) const - { - return(a.physical() == m_physical - && a.logical() == m_logical - && a.is_compressed() == m_is_compressed); - } - -private: - - /* For non compressed tablespaces, physical page size is equal to - the logical page size and the data is stored in buf_page_t::frame - (and is also always equal to univ_page_size (--innodb-page-size=)). - - For compressed tablespaces, physical page size is the compressed - page size as stored on disk and in buf_page_t::zip::data. The logical - page size is the uncompressed page size in memory - the size of - buf_page_t::frame (currently also always equal to univ_page_size - (--innodb-page-size=)). */ - - /** Physical page size. */ - unsigned m_physical:PAGE_SIZE_T_SIZE_BITS; - - /** Logical page size. */ - unsigned m_logical:PAGE_SIZE_T_SIZE_BITS; - - /** Flag designating whether the physical page is compressed, which is - true IFF the whole tablespace where the page belongs is compressed. */ - unsigned m_is_compressed:1; -}; - -/* Overloading the global output operator to conveniently print an object -of type the page_size_t. -@param[in,out] out the output stream -@param[in] obj an object of type page_size_t to be printed -@retval the output stream */ -inline -std::ostream& -operator<<( - std::ostream& out, - const page_size_t& obj) -{ - out << "[page size: physical=" << obj.physical() - << ", logical=" << obj.logical() - << ", compressed=" << obj.is_compressed() << "]"; - return(out); -} - -extern page_size_t univ_page_size; - -#endif /* page0size_t */ diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h index 1e11897482f..42432d08ad9 100644 --- a/storage/innobase/include/page0zip.h +++ b/storage/innobase/include/page0zip.h @@ -2,7 +2,7 @@ Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -86,15 +86,10 @@ page_zip_set_size( @param[in] comp nonzero=compact format @param[in] n_fields number of fields in the record; ignored if tablespace is not compressed -@param[in] page_size page size -@return FALSE if the entire record can be stored locally on the page */ -UNIV_INLINE -ibool -page_zip_rec_needs_ext( - ulint rec_size, - ulint comp, - ulint n_fields, - const page_size_t& page_size) +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@return false if the entire record can be stored locally on the page */ +inline bool page_zip_rec_needs_ext(ulint rec_size, ulint comp, ulint n_fields, + ulint zip_size) MY_ATTRIBUTE((warn_unused_result)); /**********************************************************************//** diff --git a/storage/innobase/include/page0zip.ic b/storage/innobase/include/page0zip.ic index 10a311089dc..a187f7e0111 100644 --- a/storage/innobase/include/page0zip.ic +++ b/storage/innobase/include/page0zip.ic @@ -2,7 +2,7 @@ Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -149,19 +149,14 @@ page_zip_set_size( @param[in] comp nonzero=compact format @param[in] n_fields number of fields in the record; ignored if tablespace is not compressed -@param[in] page_size page size -@return FALSE if the entire record can be stored locally on the page */ -UNIV_INLINE -ibool -page_zip_rec_needs_ext( - ulint rec_size, - ulint comp, - ulint n_fields, - const page_size_t& page_size) +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 +@return false if the entire record can be stored locally on the page */ +inline bool page_zip_rec_needs_ext(ulint rec_size, ulint comp, ulint n_fields, + ulint zip_size) { ut_ad(rec_size > ulint(comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES)); - ut_ad(comp || !page_size.is_compressed()); + ut_ad(comp || !zip_size); #if UNIV_PAGE_SIZE_MAX > COMPRESSED_REC_MAX_DATA_SIZE if (comp ? rec_size >= COMPRESSED_REC_MAX_DATA_SIZE : @@ -170,7 +165,7 @@ page_zip_rec_needs_ext( } #endif - if (page_size.is_compressed()) { + if (zip_size) { ut_ad(comp); /* On a compressed page, there is a two-byte entry in the dense page directory for every record. But there @@ -179,7 +174,7 @@ page_zip_rec_needs_ext( the encoded heap number. Check also the available space on the uncompressed page. */ return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2 - 1) - >= page_zip_empty_size(n_fields, page_size.physical()) + >= page_zip_empty_size(n_fields, zip_size) || rec_size >= page_get_free_space_of_empty(TRUE) / 2); } diff --git a/storage/innobase/include/row0ext.h b/storage/innobase/include/row0ext.h index fe4bd710156..651dab9f6e3 100644 --- a/storage/innobase/include/row0ext.h +++ b/storage/innobase/include/row0ext.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -29,7 +30,7 @@ Created September 2006 Marko Makela #include "data0types.h" #include "mem0mem.h" #include "dict0types.h" -#include "page0size.h" +#include "fsp0types.h" #include "row0types.h" /********************************************************************//** @@ -43,7 +44,7 @@ row_ext_create( in the InnoDB table object, as reported by dict_col_get_no(); NOT relative to the records in the clustered index */ - ulint flags, /*!< in: table->flags */ + const dict_table_t& table, /*!< in: table */ const dtuple_t* tuple, /*!< in: data tuple containing the field references of the externally stored columns; must be indexed by col_no; @@ -91,9 +92,7 @@ struct row_ext_t{ REC_ANTELOPE_MAX_INDEX_COL_LEN or REC_VERSION_56_MAX_INDEX_COL_LEN depending on row format */ - page_size_t page_size; - /*!< page size of the externally stored - columns */ + ulint zip_size;/*!< ROW_FORMAT=COMPRESSED page size, or 0 */ ulint len[1]; /*!< prefix lengths; 0 if not cached */ }; diff --git a/storage/innobase/include/trx0rseg.ic b/storage/innobase/include/trx0rseg.ic index 9edfe897155..1257ffcb391 100644 --- a/storage/innobase/include/trx0rseg.ic +++ b/storage/innobase/include/trx0rseg.ic @@ -41,7 +41,7 @@ trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr) || !srv_was_started); buf_block_t* block = buf_page_get(page_id_t(space->id, page_no), - univ_page_size, RW_X_LATCH, mtr); + 0, RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_RSEG_HEADER); @@ -67,8 +67,7 @@ trx_rsegf_get_new( || !srv_was_started); ut_ad(space <= TRX_SYS_MAX_UNDO_SPACES || space == SRV_TMP_SPACE_ID); - block = buf_page_get( - page_id_t(space, page_no), univ_page_size, RW_X_LATCH, mtr); + block = buf_page_get(page_id_t(space, page_no), 0, RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW); diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 92f24d036ae..205a28033a7 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -74,7 +74,7 @@ trx_sysf_get(mtr_t* mtr, bool rw = true) { buf_block_t* block = buf_page_get( page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO), - univ_page_size, rw ? RW_X_LATCH : RW_S_LATCH, mtr); + 0, rw ? RW_X_LATCH : RW_S_LATCH, mtr); if (block) { buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER); } diff --git a/storage/innobase/include/trx0undo.ic b/storage/innobase/include/trx0undo.ic index f6106ffddfa..b54f73cdda6 100644 --- a/storage/innobase/include/trx0undo.ic +++ b/storage/innobase/include/trx0undo.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -111,8 +111,7 @@ UNIV_INLINE page_t* trx_undo_page_get(const page_id_t page_id, mtr_t* mtr) { - buf_block_t* block = buf_page_get(page_id, univ_page_size, - RW_X_LATCH, mtr); + buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); @@ -127,8 +126,7 @@ UNIV_INLINE page_t* trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr) { - buf_block_t* block = buf_page_get(page_id, univ_page_size, - RW_S_LATCH, mtr); + buf_block_t* block = buf_page_get(page_id, 0, RW_S_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index a8877ab8a33..0433a04e6f8 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -5176,7 +5176,7 @@ lock_rec_block_validate( block = buf_page_get_gen( page_id_t(space_id, page_no), - page_size_t(space->flags), + space->zip_size(), RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, __FILE__, __LINE__, &mtr, &err); diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 720bb94f012..a39b46b53be 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -719,7 +719,7 @@ log_file_header_flush( fil_io(IORequestLogWrite, true, page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no), - univ_page_size, + 0, ulint(dest_offset & (srv_page_size - 1)), OS_FILE_LOG_BLOCK_SIZE, buf, NULL); @@ -838,7 +838,7 @@ loop: fil_io(IORequestLogWrite, true, page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no), - univ_page_size, + 0, ulint(next_offset & (srv_page_size - 1)), write_len, buf, NULL); srv_stats.os_log_pending_writes.dec(); @@ -1341,7 +1341,7 @@ log_group_checkpoint(lsn_t end_lsn) fil_io(IORequestLogWrite, false, page_id_t(SRV_LOG_SPACE_FIRST_ID, 0), - univ_page_size, + 0, (log_sys.next_checkpoint_no & 1) ? LOG_CHECKPOINT_2 : LOG_CHECKPOINT_1, OS_FILE_LOG_BLOCK_SIZE, @@ -1361,7 +1361,7 @@ void log_header_read(ulint header) fil_io(IORequestLogRead, true, page_id_t(SRV_LOG_SPACE_FIRST_ID, header >> srv_page_size_shift), - univ_page_size, header & (srv_page_size - 1), + 0, header & (srv_page_size - 1), OS_FILE_LOG_BLOCK_SIZE, log_sys.checkpoint_buf, NULL); } diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 9f6b9243070..9b7866c3d1a 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -780,7 +780,7 @@ loop: fil_io(IORequestLogRead, true, page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no), - univ_page_size, + 0, ulint(source_offset & (srv_page_size - 1)), len, buf, NULL); @@ -997,7 +997,7 @@ static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt) fil_io(IORequestLogRead, true, page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no), - univ_page_size, + 0, ulint((source_offset & ~(OS_FILE_LOG_BLOCK_SIZE - 1)) & (srv_page_size - 1)), OS_FILE_LOG_BLOCK_SIZE, buf, NULL); @@ -2081,19 +2081,21 @@ void recv_apply_hashed_log_recs(bool last_batch) if (recv_addr->state == RECV_DISCARDED || !UT_LIST_GET_LEN(recv_addr->rec_list)) { +not_found: ut_a(recv_sys->n_addrs); recv_sys->n_addrs--; continue; } + fil_space_t* space = fil_space_acquire_for_io( + recv_addr->space); + if (!space) { + goto not_found; + } + const page_id_t page_id(recv_addr->space, recv_addr->page_no); - bool found; - const page_size_t& page_size - = fil_space_get_page_size(recv_addr->space, - &found); - - ut_ad(found); + const ulint zip_size = space->zip_size(); if (recv_addr->state == RECV_NOT_PROCESSED) { mutex_exit(&recv_sys->mutex); @@ -2103,7 +2105,7 @@ void recv_apply_hashed_log_recs(bool last_batch) mtr.start(); buf_block_t* block = buf_page_get( - page_id, page_size, + page_id, zip_size, RW_X_LATCH, &mtr); buf_block_dbg_add_level( @@ -2117,6 +2119,8 @@ void recv_apply_hashed_log_recs(bool last_batch) mutex_enter(&recv_sys->mutex); } + + space->release_for_io(); } } diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index 13934546448..5c15e8238d2 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -142,7 +142,7 @@ struct FindPage slot->object); if (m_ptr < block->frame - || m_ptr >= block->frame + block->page.size.logical()) { + || m_ptr >= block->frame + srv_page_size) { return(true); } diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index f7a436ed68e..bb51123617d 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -3511,8 +3511,6 @@ static WinIoInit win_io_init; /** Free storage space associated with a section of the file. @param[in] fh Open file handle -@param[in] page_size Tablespace page size -@param[in] block_size File system block size @param[in] off Starting offset (SEEK_SET) @param[in] len Size of the hole @return 0 on success or errno */ diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index 96f5603853b..6c213f28c12 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -26,19 +26,19 @@ Created June 2005 by Marko Makela *******************************************************/ #include "page0zip.h" -#include "page0size.h" +#include "fsp0types.h" #include "page0page.h" #include "buf0checksum.h" +#include "ut0crc32.h" +#include "zlib.h" + +#ifndef UNIV_INNOCHECKSUM /** A BLOB field reference full of zero, for use in assertions and tests. Initially, BLOB field references are set to zero, in dtuple_convert_big_rec(). */ const byte field_ref_zero[UNIV_PAGE_SIZE_MAX] = { 0, }; -#include "ut0crc32.h" -#include "zlib.h" - -#ifndef UNIV_INNOCHECKSUM #include "mtr0log.h" #include "dict0dict.h" #include "btr0cur.h" @@ -170,18 +170,17 @@ page_zip_is_too_big( const dict_index_t* index, const dtuple_t* entry) { - const page_size_t& page_size = - dict_table_page_size(index->table); + const ulint zip_size = index->table->space->zip_size(); /* Estimate the free space of an empty compressed page. Subtract one byte for the encoded heap_no in the modification log. */ ulint free_space_zip = page_zip_empty_size( - index->n_fields, page_size.physical()); + index->n_fields, zip_size); ulint n_uniq = dict_index_get_n_unique_in_tree(index); ut_ad(dict_table_is_comp(index->table)); - ut_ad(page_size.is_compressed()); + ut_ad(zip_size); if (free_space_zip == 0) { return(true); diff --git a/storage/innobase/row/row0ext.cc b/storage/innobase/row/row0ext.cc index 503f7d0d3e7..6973fe758d9 100644 --- a/storage/innobase/row/row0ext.cc +++ b/storage/innobase/row/row0ext.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -29,14 +30,14 @@ Created September 2006 Marko Makela /** Fills the column prefix cache of an externally stored column. @param[in,out] ext column prefix cache @param[in] i index of ext->ext[] -@param[in] page_size page size +@param[in] space tablespace @param[in] dfield data field */ static void row_ext_cache_fill( row_ext_t* ext, ulint i, - const page_size_t& page_size, + fil_space_t* space, const dfield_t* dfield) { const byte* field = static_cast( @@ -75,7 +76,8 @@ row_ext_cache_fill( crashed during the execution of btr_free_externally_stored_field(). */ ext->len[i] = btr_copy_externally_stored_field_prefix( - buf, ext->max_len, page_size, field, f_len); + buf, ext->max_len, ext->zip_size, + field, f_len); } } } @@ -91,7 +93,7 @@ row_ext_create( in the InnoDB table object, as reported by dict_col_get_no(); NOT relative to the records in the clustered index */ - ulint flags, /*!< in: table->flags */ + const dict_table_t& table, /*!< in: table */ const dtuple_t* tuple, /*!< in: data tuple containing the field references of the externally stored columns; must be indexed by col_no; @@ -100,36 +102,30 @@ row_ext_create( to prevent deletion (rollback or purge). */ mem_heap_t* heap) /*!< in: heap where created */ { - ulint i; - const page_size_t& page_size = dict_tf_get_page_size(flags); - - row_ext_t* ret; + if (!table.space) { + return NULL; + } ut_ad(n_ext > 0); - ret = static_cast( + row_ext_t* ret = static_cast( mem_heap_alloc(heap, (sizeof *ret) + (n_ext - 1) * sizeof ret->len)); ret->n_ext = n_ext; ret->ext = ext; - ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags); - ret->page_size.copy_from(page_size); + ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(table.flags); + ret->zip_size = dict_tf_get_zip_size(table.flags); ret->buf = static_cast( mem_heap_alloc(heap, n_ext * ret->max_len)); -#ifdef UNIV_DEBUG - memset(ret->buf, 0xaa, n_ext * ret->max_len); - UNIV_MEM_ALLOC(ret->buf, n_ext * ret->max_len); -#endif - /* Fetch the BLOB prefixes */ - for (i = 0; i < n_ext; i++) { + for (ulint i = 0; i < n_ext; i++) { const dfield_t* dfield; dfield = dtuple_get_nth_field(tuple, ext[i]); - row_ext_cache_fill(ret, i, page_size, dfield); + row_ext_cache_fill(ret, i, table.space, dfield); } return(ret); diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 19b6dfd0763..4e3a4b0c4c7 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -808,7 +808,7 @@ DECLARE_THREAD(fts_parallel_tokenization)( block = psort_info->merge_block; crypt_block = psort_info->crypt_block; - const page_size_t& page_size = dict_table_page_size(table); + const ulint zip_size = table->space->zip_size(); row_merge_fts_get_next_doc_item(psort_info, &doc_item); @@ -838,7 +838,7 @@ loop: doc.text.f_str = btr_copy_externally_stored_field( &doc.text.f_len, data, - page_size, data_len, blob_heap); + zip_size, data_len, blob_heap); } else { doc.text.f_str = data; doc.text.f_len = data_len; diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 4e9f16a502f..60e1d5a202e 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -53,7 +53,7 @@ Created 2012-02-08 by Sunny Bains. /** The size of the buffer to use for IO. @param n physical page size @return number of pages */ -#define IO_BUFFER_SIZE(n) ((1024 * 1024) / n) +#define IO_BUFFER_SIZE(n) ((1024 * 1024) / (n)) /** For gathering stats on records during phase I */ struct row_stats_t { @@ -115,7 +115,7 @@ struct row_import { m_hostname(NULL), m_table_name(NULL), m_autoinc(0), - m_page_size(0, 0, false), + m_zip_size(0), m_flags(0), m_n_cols(0), m_cols(NULL), @@ -196,7 +196,8 @@ struct row_import { ib_uint64_t m_autoinc; /*!< Next autoinc value */ - page_size_t m_page_size; /*!< Tablespace page size */ + ulint m_zip_size; /*!< ROW_FORMAT=COMPRESSED + page size, or 0 */ ulint m_flags; /*!< Table flags */ @@ -356,7 +357,7 @@ public: @param trx covering transaction */ AbstractCallback(trx_t* trx, ulint space_id) : - m_page_size(0, 0, false), + m_zip_size(0), m_trx(trx), m_space(space_id), m_xdes(), @@ -380,7 +381,7 @@ public: /** @return true if compressed table. */ bool is_compressed_table() const UNIV_NOTHROW { - return(get_page_size().is_compressed()); + return get_zip_size(); } /** @return the tablespace flags */ @@ -400,7 +401,11 @@ public: m_filepath = filename; } - const page_size_t& get_page_size() const { return m_page_size; } + ulint get_zip_size() const { return m_zip_size; } + ulint physical_size() const + { + return m_zip_size ? m_zip_size : srv_page_size; + } const char* filename() const { return m_filepath; } @@ -439,7 +444,7 @@ protected: { ulint offset; - offset = xdes_calc_descriptor_index(get_page_size(), page_no); + offset = xdes_calc_descriptor_index(get_zip_size(), page_no); return(page + XDES_ARR_OFFSET + XDES_SIZE * offset); } @@ -467,9 +472,11 @@ protected: state = mach_read_ulint(xdesc + XDES_STATE, MLOG_4BYTES); if (state != XDES_FREE) { + const ulint physical_size = m_zip_size + ? m_zip_size : srv_page_size; m_xdes = UT_NEW_ARRAY_NOKEY(xdes_t, - m_page_size.physical()); + physical_size); /* Trigger OOM */ DBUG_EXECUTE_IF( @@ -482,7 +489,7 @@ protected: return(DB_OUT_OF_MEMORY); } - memcpy(m_xdes, page, m_page_size.physical()); + memcpy(m_xdes, page, physical_size); } return(DB_SUCCESS); @@ -493,7 +500,7 @@ protected: @return true if the page is marked as free */ bool is_free(ulint page_no) const UNIV_NOTHROW { - ut_a(xdes_calc_descriptor_page(get_page_size(), page_no) + ut_a(xdes_calc_descriptor_page(get_zip_size(), page_no) == m_xdes_page_no); if (m_xdes != 0) { @@ -508,8 +515,8 @@ protected: } protected: - /** The tablespace page size. */ - page_size_t m_page_size; + /** The ROW_FORMAT=COMPRESSED page size, or 0. */ + ulint m_zip_size; /** File handle to the tablespace */ pfs_os_file_t m_file; @@ -568,21 +575,23 @@ AbstractCallback::init( /* Clear the DATA_DIR flag, which is basically garbage. */ m_space_flags &= ~(1U << FSP_FLAGS_POS_RESERVED); - m_page_size.copy_from(page_size_t(m_space_flags)); + m_zip_size = fil_space_t::zip_size(m_space_flags); + const ulint logical_size = fil_space_t::logical_size(m_space_flags); + const ulint physical_size = fil_space_t::physical_size(m_space_flags); - if (!is_compressed_table() && !m_page_size.equals_to(univ_page_size)) { + if (logical_size != srv_page_size) { - ib::error() << "Page size " << m_page_size.physical() + ib::error() << "Page size " << logical_size << " of ibd file is not the same as the server page" " size " << srv_page_size; return(DB_CORRUPTION); - } else if (file_size % m_page_size.physical() != 0) { + } else if (file_size & (physical_size - 1)) { ib::error() << "File size " << file_size << " is not a" " multiple of the page size " - << m_page_size.physical(); + << physical_size; return(DB_CORRUPTION); } @@ -694,7 +703,7 @@ FetchIndexRootPages::build_row_import(row_import* cfg) const UNIV_NOTHROW Indexes::const_iterator end = m_indexes.end(); ut_a(cfg->m_table == m_table); - cfg->m_page_size.copy_from(m_page_size); + cfg->m_zip_size = m_zip_size; cfg->m_n_indexes = m_indexes.size(); if (cfg->m_n_indexes == 0) { @@ -1980,7 +1989,7 @@ dberr_t PageConverter::operator()(buf_block_t* block) UNIV_NOTHROW /* If we already had an old page with matching number in the buffer pool, evict it now, because we no longer evict the pages on DISCARD TABLESPACE. */ - buf_page_get_gen(block->page.id, get_page_size(), + buf_page_get_gen(block->page.id, get_zip_size(), RW_NO_LATCH, NULL, BUF_EVICT_IF_IN_POOL, __FILE__, __LINE__, NULL, NULL); @@ -2000,7 +2009,7 @@ dberr_t PageConverter::operator()(buf_block_t* block) UNIV_NOTHROW /* Calculate and update the checksum of non-index pages for ROW_FORMAT=COMPRESSED tables. */ buf_flush_update_zip_checksum( - block->page.zip.data, get_page_size().physical(), + block->page.zip.data, block->zip_size(), m_current_lsn); } @@ -2904,10 +2913,7 @@ row_import_read_v1( cfg->m_flags = mach_read_from_4(ptr); ptr += sizeof(ib_uint32_t); - cfg->m_page_size.copy_from(dict_tf_get_page_size(cfg->m_flags)); - - ut_a(logical_page_size == cfg->m_page_size.logical()); - + cfg->m_zip_size = dict_tf_get_zip_size(cfg->m_flags); cfg->m_n_cols = mach_read_from_4(ptr); if (!dict_tf_is_valid(cfg->m_flags)) { @@ -3265,7 +3271,7 @@ fil_iterate( AbstractCallback& callback) { os_offset_t offset; - const ulint size = callback.get_page_size().physical(); + const ulint size = callback.physical_size(); ulint n_bytes = iter.n_io_buffers * size; const ulint buf_size = srv_page_size @@ -3390,13 +3396,13 @@ not_encrypted: } } else { if (!fil_space_verify_crypt_checksum( - src, callback.get_page_size())) { + src, callback.get_zip_size())) { goto page_corrupted; } decrypted = fil_space_decrypt( iter.crypt_data, dst, - callback.get_page_size(), src, &err); + callback.physical_size(), src, &err); if (err != DB_SUCCESS) { goto func_exit; @@ -3423,7 +3429,7 @@ not_encrypted: false, encrypted && !frame_changed ? dst : src, - callback.get_page_size(), NULL)) { + callback.get_zip_size(), NULL)) { goto page_corrupted; } @@ -3500,7 +3506,7 @@ not_encrypted: block->page.id.space(), block->page.id.page_no(), mach_read_from_8(src + FIL_PAGE_LSN), - src, callback.get_page_size(), dest); + src, block->zip_size(), dest); if (tmp == src) { /* TODO: remove unnecessary memcpy's */ @@ -3625,10 +3631,8 @@ fil_tablespace_iterate( if (err == DB_SUCCESS) { block->page.id = page_id_t(callback.get_space_id(), 0); - block->page.size.copy_from(callback.get_page_size()); - if (block->page.size.is_compressed()) { - page_zip_set_size(&block->page.zip, - callback.get_page_size().physical()); + if (ulint zip_size = callback.get_zip_size()) { + page_zip_set_size(&block->page.zip, zip_size); /* ROW_FORMAT=COMPRESSED is not optimised for block IO for now. We do the IMPORT page by page. */ n_io_buffers = 1; @@ -3638,7 +3642,7 @@ fil_tablespace_iterate( /* read (optional) crypt data */ iter.crypt_data = fil_space_read_crypt_data( - callback.get_page_size(), page); + callback.get_zip_size(), page); /* If tablespace is encrypted, it needs extra buffers */ if (iter.crypt_data && n_io_buffers > 1) { @@ -3819,12 +3823,12 @@ row_import_for_mysql( ut_a(err == DB_FAIL); - cfg.m_page_size.copy_from(univ_page_size); + cfg.m_zip_size = 0; FetchIndexRootPages fetchIndexRootPages(table, trx); err = fil_tablespace_iterate( - table, IO_BUFFER_SIZE(cfg.m_page_size.physical()), + table, IO_BUFFER_SIZE(srv_page_size), fetchIndexRootPages); if (err == DB_SUCCESS) { @@ -3862,7 +3866,8 @@ row_import_for_mysql( /* Set the IO buffer size in pages. */ err = fil_tablespace_iterate( - table, IO_BUFFER_SIZE(cfg.m_page_size.physical()), converter); + table, IO_BUFFER_SIZE(cfg.m_zip_size ? cfg.m_zip_size + : srv_page_size), converter); DBUG_EXECUTE_IF("ib_import_reset_space_and_lsn_failure", err = DB_TOO_MANY_CONCURRENT_TRXS;); diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 09df80f789d..5701a4af233 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -1139,7 +1139,7 @@ ALTER TABLE) table @param[in] offsets rec_get_offsets(rec) @param[in] i rec field corresponding to col -@param[in] page_size page size of the old table +@param[in] zip_size ROW_FORMAT=COMPRESSED size of the old table @param[in] max_len maximum length of dfield @param[in] log row log for the table @retval DB_INVALID_NULL if a NULL value is encountered @@ -1153,7 +1153,7 @@ row_log_table_get_pk_col( const rec_t* rec, const ulint* offsets, ulint i, - const page_size_t& page_size, + ulint zip_size, ulint max_len, const row_log_t* log) { @@ -1192,7 +1192,7 @@ row_log_table_get_pk_col( mem_heap_alloc(heap, field_len)); len = btr_copy_externally_stored_field_prefix( - blob_field, field_len, page_size, field, len); + blob_field, field_len, zip_size, field, len); if (len >= max_len + 1) { return(DB_TOO_BIG_INDEX_COL); } @@ -1307,8 +1307,7 @@ row_log_table_get_pk( const ulint max_len = DICT_MAX_FIELD_LEN_BY_FORMAT(new_table); - const page_size_t& page_size - = dict_table_page_size(index->table); + const ulint zip_size = index->table->space->zip_size(); for (ulint new_i = 0; new_i < new_n_uniq; new_i++) { dict_field_t* ifield; @@ -1335,7 +1334,8 @@ row_log_table_get_pk( log->error = row_log_table_get_pk_col( ifield, dfield, *heap, - rec, offsets, i, page_size, max_len, log); + rec, offsets, i, zip_size, max_len, + log); if (log->error != DB_SUCCESS) { err_exit: @@ -1602,7 +1602,7 @@ row_log_table_apply_convert_mrec( data = btr_rec_copy_externally_stored_field( mrec, offsets, - dict_table_page_size(index->table), + index->table->space->zip_size(), i, &len, heap); ut_a(data); dfield_set_data(dfield, data, len); @@ -2676,8 +2676,8 @@ ulint row_log_progress_inc_per_block() { /* We must increment the progress once per page (as in - univ_page_size, usually 16KiB). One block here is srv_sort_buf_size - (usually 1MiB). */ + srv_page_size, default = innodb_page_size=16KiB). + One block here is srv_sort_buf_size (usually 1MiB). */ const ulint pages_per_block = std::max( ulint(srv_sort_buf_size >> srv_page_size_shift), 1); diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 50d70b22a5a..f1776dd07ee 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -442,7 +442,7 @@ row_merge_buf_redundant_convert( const dfield_t* row_field, dfield_t* field, ulint len, - const page_size_t& page_size, + ulint zip_size, mem_heap_t* heap) { ut_ad(field->type.mbminlen == 1); @@ -462,7 +462,7 @@ row_merge_buf_redundant_convert( field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE)); byte* data = btr_copy_externally_stored_field( - &ext_len, field_data, page_size, field_len, heap); + &ext_len, field_data, zip_size, field_len, heap); ut_ad(ext_len < len); @@ -704,7 +704,7 @@ row_merge_buf_add( if (conv_heap != NULL) { row_merge_buf_redundant_convert( row_field, field, col->len, - dict_table_page_size(old_table), + old_table->space->zip_size(), conv_heap); } else { /* Field length mismatch should not @@ -2036,7 +2036,7 @@ end_of_index: block = btr_block_get( page_id_t(block->page.id.space(), next_page_no), - block->page.size, + block->zip_size(), BTR_SEARCH_LEAF, clust_index, &mtr); @@ -3424,7 +3424,7 @@ void row_merge_copy_blobs( const mrec_t* mrec, const ulint* offsets, - const page_size_t& page_size, + ulint zip_size, dtuple_t* tuple, mem_heap_t* heap) { @@ -3462,10 +3462,10 @@ row_merge_copy_blobs( BTR_EXTERN_FIELD_REF_SIZE)); data = btr_copy_externally_stored_field( - &len, field_data, page_size, field_len, heap); + &len, field_data, zip_size, field_len, heap); } else { data = btr_rec_copy_externally_stored_field( - mrec, offsets, page_size, i, &len, heap); + mrec, offsets, zip_size, i, &len, heap); } /* Because we have locked the table, any records @@ -3663,8 +3663,7 @@ row_merge_insert_index_tuples( row_log_table_blob_alloc() and row_log_table_blob_free(). */ row_merge_copy_blobs( - mrec, offsets, - dict_table_page_size(old_table), + mrec, offsets, old_table->space->zip_size(), dtuple, tuple_heap); } diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 28c6a1abf21..0f0032c9b86 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3361,8 +3361,7 @@ row_drop_table_for_mysql( for (dict_index_t* index = dict_table_get_first_index(table); index != NULL; index = dict_table_get_next_index(index)) { - btr_free(page_id_t(SRV_TMP_SPACE_ID, index->page), - univ_page_size); + btr_free(page_id_t(SRV_TMP_SPACE_ID, index->page)); } /* Remove the pointer to this table object from the list of modified tables by the transaction because the object diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index f0652ed3d54..633fc0f049f 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -992,7 +992,7 @@ skip_secondaries: block = buf_page_get( page_id_t(rseg->space->id, page_no), - univ_page_size, RW_X_LATCH, &mtr); + 0, RW_X_LATCH, &mtr); buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index 3c03f8277ae..400faba0d88 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -151,7 +151,7 @@ static bool row_build_spatial_index_key( temp_heap = mem_heap_create(1000); dptr = btr_copy_externally_stored_field( - &dlen, dptr, ext ? ext->page_size : page_size_t(space->flags), + &dlen, dptr, ext ? ext->zip_size : space->zip_size(), flen, temp_heap); write_mbr: @@ -593,7 +593,7 @@ row_build_low( row_log_table_delete(). */ } else if (j) { - *ext = row_ext_create(j, ext_cols, index->table->flags, row, + *ext = row_ext_create(j, ext_cols, *index->table, row, heap); } else { *ext = NULL; diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 8d7824bfc56..215ed0fe1e9 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -2,7 +2,7 @@ Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -127,7 +127,7 @@ row_sel_sec_rec_is_for_blob( } len = btr_copy_externally_stored_field_prefix( - buf, prefix_len, page_size_t(table->space->flags), + buf, prefix_len, table->space->zip_size(), clust_field, clust_len); if (len == 0) { @@ -308,8 +308,7 @@ row_sel_sec_rec_is_for_clust_rec( if (rec_offs_nth_extern(clust_offs, clust_pos)) { dptr = btr_copy_externally_stored_field( &clust_len, dptr, - page_size_t(clust_index->table->space - ->flags), + clust_index->table->space->zip_size(), len, heap); } @@ -532,7 +531,7 @@ row_sel_fetch_columns( data = btr_rec_copy_externally_stored_field( rec, offsets, - dict_table_page_size(index->table), + index->table->space->zip_size(), field_no, &len, heap); /* data == NULL means that the @@ -1135,7 +1134,7 @@ re_scan: cur_block = buf_page_get_gen( page_id_t(index->table->space_id, page_no), - page_size_t(index->table->space->flags), + index->table->space->zip_size(), RW_X_LATCH, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err); } else { @@ -2933,8 +2932,7 @@ row_sel_store_mysql_field( causes an assert */ data = btr_rec_copy_externally_stored_field( - rec, offsets, - dict_table_page_size(prebuilt->table), + rec, offsets, prebuilt->table->space->zip_size(), field_no, &len, heap); if (UNIV_UNLIKELY(!data)) { @@ -3308,7 +3306,7 @@ row_sel_get_clust_rec_for_mysql( and is it not unsafe to use RW_NO_LATCH here? */ buf_block_t* block = buf_page_get_gen( btr_pcur_get_block(prebuilt->pcur)->page.id, - btr_pcur_get_block(prebuilt->pcur)->page.size, + btr_pcur_get_block(prebuilt->pcur)->zip_size(), RW_NO_LATCH, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err); mem_heap_t* heap = mem_heap_create(256); diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index e8ee3aeac30..6be66d1d56c 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1131,7 +1131,7 @@ of the column and must not be poisoned with the new values. @param[in] data 'internally' stored part of the field containing also the reference to the external part @param[in] local_len length of data, in bytes -@param[in] page_size BLOB page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] len input - length of prefix to fetch; output: fetched length of the prefix @param[in,out] heap heap where to allocate @@ -1141,14 +1141,14 @@ byte* row_upd_ext_fetch( const byte* data, ulint local_len, - const page_size_t& page_size, + ulint zip_size, ulint* len, mem_heap_t* heap) { byte* buf = static_cast(mem_heap_alloc(heap, *len)); *len = btr_copy_externally_stored_field_prefix( - buf, *len, page_size, data, local_len); + buf, *len, zip_size, data, local_len); /* We should never update records containing a half-deleted BLOB. */ ut_a(*len); @@ -1164,7 +1164,7 @@ the given index entry field. @param[in] uf update field @param[in,out] heap memory heap for allocating and copying the new value -@param[in] page_size page size */ +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 */ static void row_upd_index_replace_new_col_val( @@ -1173,7 +1173,7 @@ row_upd_index_replace_new_col_val( const dict_col_t* col, const upd_field_t* uf, mem_heap_t* heap, - const page_size_t& page_size) + ulint zip_size) { ulint len; const byte* data; @@ -1197,7 +1197,7 @@ row_upd_index_replace_new_col_val( len = field->prefix_len; - data = row_upd_ext_fetch(data, l, page_size, + data = row_upd_ext_fetch(data, l, zip_size, &len, heap); } @@ -1270,7 +1270,7 @@ row_upd_index_replace_metadata( ut_ad(update->is_alter_metadata()); ut_ad(entry->info_bits == update->info_bits); ut_ad(entry->n_fields == ulint(index->n_fields) + 1); - const page_size_t& page_size = dict_table_page_size(index->table); + const ulint zip_size = index->table->space->zip_size(); const ulint first = index->first_user_field(); ut_d(bool found_mblob = false); @@ -1298,7 +1298,7 @@ row_upd_index_replace_metadata( f -= f > first; const dict_field_t* field = dict_index_get_nth_field(index, f); row_upd_index_replace_new_col_val(dfield, field, field->col, - uf, heap, page_size); + uf, heap, zip_size); } ut_ad(found_mblob); @@ -1326,7 +1326,7 @@ row_upd_index_replace_new_col_vals_index_pos( return; } - const page_size_t& page_size = dict_table_page_size(index->table); + const ulint zip_size = index->table->space->zip_size(); dtuple_set_info_bits(entry, update->info_bits); @@ -1352,7 +1352,7 @@ row_upd_index_replace_new_col_vals_index_pos( if (uf) { row_upd_index_replace_new_col_val( dtuple_get_nth_field(entry, i), - field, col, uf, heap, page_size); + field, col, uf, heap, zip_size); } } } @@ -1378,7 +1378,7 @@ row_upd_index_replace_new_col_vals( ulint i; const dict_index_t* clust_index = dict_table_get_first_index(index->table); - const page_size_t& page_size = dict_table_page_size(index->table); + const ulint zip_size = index->table->space->zip_size(); ut_ad(!index->table->skip_alter_undo); @@ -1408,7 +1408,7 @@ row_upd_index_replace_new_col_vals( if (uf) { row_upd_index_replace_new_col_val( dtuple_get_nth_field(entry, i), - field, col, uf, heap, page_size); + field, col, uf, heap, zip_size); } } } @@ -1632,8 +1632,7 @@ row_upd_replace( } if (n_ext_cols) { - *ext = row_ext_create(n_ext_cols, ext_cols, table->flags, row, - heap); + *ext = row_ext_create(n_ext_cols, ext_cols, *table, row, heap); } else { *ext = NULL; } @@ -1741,11 +1740,9 @@ row_upd_changes_ord_field_binary_func( mem_heap_t* temp_heap = NULL; const dfield_t* new_field = &upd_field->new_val; - const page_size_t page_size - = (ext != NULL) - ? ext->page_size - : dict_table_page_size( - index->table); + const ulint zip_size = ext + ? ext->zip_size + : index->table->space->zip_size(); ut_ad(dfield->data != NULL && dfield->len > GEO_DATA_HEADER_SIZE); @@ -1762,7 +1759,7 @@ row_upd_changes_ord_field_binary_func( dptr = btr_copy_externally_stored_field( &dlen, dptr, - page_size, + zip_size, flen, temp_heap); } else { @@ -1825,7 +1822,7 @@ row_upd_changes_ord_field_binary_func( dptr = btr_copy_externally_stored_field( &dlen, dptr, - page_size, + zip_size, flen, temp_heap); } else { diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 34638dfda25..3d1415b07c6 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -194,8 +194,6 @@ ulong srv_page_size_shift; /** innodb_log_write_ahead_size */ ulong srv_log_write_ahead_size; -page_size_t univ_page_size(0, 0, false); - /** innodb_adaptive_flushing; try to flush dirty pages so as to avoid IO bursts at the checkpoints. */ my_bool srv_adaptive_flushing; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 108e9182f00..46de5ec812d 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1887,7 +1887,7 @@ files_checked: /* New data file(s) were added */ mtr.start(); buf_block_t* block = buf_page_get( - page_id_t(0, 0), univ_page_size, + page_id_t(0, 0), 0, RW_SX_LATCH, &mtr); ulint size = mach_read_from_4( FSP_HEADER_OFFSET + FSP_SIZE @@ -1911,8 +1911,7 @@ files_checked: #ifdef UNIV_DEBUG { mtr.start(); - buf_block_t* block = buf_page_get(page_id_t(0, 0), - univ_page_size, + buf_block_t* block = buf_page_get(page_id_t(0, 0), 0, RW_S_LATCH, &mtr); ut_ad(mach_read_from_4(FSP_SIZE + FSP_HEADER_OFFSET + block->frame) @@ -2075,24 +2074,24 @@ files_checked: block = buf_page_get( page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO), - univ_page_size, RW_X_LATCH, &mtr); + 0, RW_X_LATCH, &mtr); fil_block_check_type(*block, FIL_PAGE_TYPE_SYS, &mtr); /* Already MySQL 3.23.53 initialized FSP_IBUF_TREE_ROOT_PAGE_NO to FIL_PAGE_INDEX. No need to reset that one. */ block = buf_page_get( page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO), - univ_page_size, RW_X_LATCH, &mtr); + 0, RW_X_LATCH, &mtr); fil_block_check_type(*block, FIL_PAGE_TYPE_TRX_SYS, &mtr); block = buf_page_get( page_id_t(TRX_SYS_SPACE, FSP_FIRST_RSEG_PAGE_NO), - univ_page_size, RW_X_LATCH, &mtr); + 0, RW_X_LATCH, &mtr); fil_block_check_type(*block, FIL_PAGE_TYPE_SYS, &mtr); block = buf_page_get( page_id_t(TRX_SYS_SPACE, FSP_DICT_HDR_PAGE_NO), - univ_page_size, RW_X_LATCH, &mtr); + 0, RW_X_LATCH, &mtr); fil_block_check_type(*block, FIL_PAGE_TYPE_SYS, &mtr); mtr.commit(); } diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 595c2a15fb3..fdb28fee8c2 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -718,7 +718,7 @@ trx_undo_rec_skip_row_ref( log of an update or delete marking of a clustered index record. @param[out] ext_buf buffer to hold the prefix data and BLOB pointer @param[in] prefix_len prefix size to store in the undo log -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] field an externally stored column @param[in,out] len input: length of field; output: used length of ext_buf @@ -728,13 +728,13 @@ byte* trx_undo_page_fetch_ext( byte* ext_buf, ulint prefix_len, - const page_size_t& page_size, + ulint zip_size, const byte* field, ulint* len) { /* Fetch the BLOB. */ ulint ext_len = btr_copy_externally_stored_field_prefix( - ext_buf, prefix_len, page_size, field, *len); + ext_buf, prefix_len, zip_size, field, *len); /* BLOBs should always be nonempty. */ ut_a(ext_len); /* Append the BLOB pointer to the prefix. */ @@ -752,7 +752,7 @@ available size, or NULL when should not fetch a longer prefix @param[in] prefix_len prefix size to store in the undo log -@param[in] page_size page size +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in,out] field the locally stored part of the externally stored column @param[in,out] len length of field, in bytes @@ -765,7 +765,7 @@ trx_undo_page_report_modify_ext( byte* ptr, byte* ext_buf, ulint prefix_len, - const page_size_t& page_size, + ulint zip_size, const byte** field, ulint* len, spatial_status_t spatial_status) @@ -807,7 +807,7 @@ trx_undo_page_report_modify_ext( ptr += mach_write_compressed(ptr, *len); *field = trx_undo_page_fetch_ext(ext_buf, prefix_len, - page_size, *field, len); + zip_size, *field, len); ptr += mach_write_compressed(ptr, *len + spatial_len); } else { @@ -820,7 +820,7 @@ trx_undo_page_report_modify_ext( /** Get MBR from a Geometry column stored externally @param[out] mbr MBR to fill -@param[in] pagesize table pagesize +@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] field field contain the geometry data @param[in,out] len length of field, in bytes */ @@ -828,17 +828,17 @@ static void trx_undo_get_mbr_from_ext( /*======================*/ - double* mbr, - const page_size_t& page_size, - const byte* field, - ulint* len) + double* mbr, + ulint zip_size, + const byte* field, + ulint* len) { uchar* dptr = NULL; ulint dlen; mem_heap_t* heap = mem_heap_create(100); dptr = btr_copy_externally_stored_field( - &dlen, field, page_size, *len, heap); + &dlen, field, zip_size, *len, heap); if (dlen <= GEO_DATA_HEADER_SIZE) { for (uint i = 0; i < SPDIMS; ++i) { @@ -1181,7 +1181,7 @@ write_field: && !ignore_prefix && flen < REC_ANTELOPE_MAX_INDEX_COL_LEN ? ext_buf : NULL, prefix_len, - dict_table_page_size(table), + table->space->zip_size(), &field, &flen, SPATIAL_UNKNOWN); *type_cmpl_ptr |= TRX_UNDO_UPD_EXTERN; @@ -1335,8 +1335,8 @@ store_len: table, col); ut_a(prefix_len < sizeof ext_buf); - const page_size_t& page_size - = dict_table_page_size(table); + const ulint zip_size + = table->space->zip_size(); /* If there is a spatial index on it, log its MBR */ @@ -1345,7 +1345,7 @@ store_len: col->mtype)); trx_undo_get_mbr_from_ext( - mbr, page_size, + mbr, zip_size, field, &flen); } @@ -1354,7 +1354,7 @@ store_len: flen < REC_ANTELOPE_MAX_INDEX_COL_LEN && !ignore_prefix ? ext_buf : NULL, prefix_len, - page_size, + zip_size, &field, &flen, spatial_status); } else { diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index e084b0b67bf..81e0b5a1945 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -187,7 +187,7 @@ trx_undo_get_prev_rec_from_prev_page( space = page_get_space_id(undo_page); buf_block_t* block = buf_page_get( - page_id_t(space, prev_page_no), univ_page_size, + page_id_t(space, prev_page_no), 0, shared ? RW_S_LATCH : RW_X_LATCH, mtr); buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE); @@ -1340,7 +1340,7 @@ trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo, buf_block_t* block = buf_page_get(page_id_t(undo->rseg->space->id, undo->hdr_page_no), - univ_page_size, RW_X_LATCH, mtr); + 0, RW_X_LATCH, mtr); if (!block) { return NULL; } @@ -1399,7 +1399,7 @@ trx_undo_assign(trx_t* trx, dberr_t* err, mtr_t* mtr) if (undo) { return buf_page_get_gen( page_id_t(undo->rseg->space->id, undo->last_page_no), - univ_page_size, RW_X_LATCH, + 0, RW_X_LATCH, buf_pool_is_obsolete(undo->withdraw_clock) ? NULL : undo->guess_block, BUF_GET, __FILE__, __LINE__, mtr, err); @@ -1455,7 +1455,7 @@ trx_undo_assign_low(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo, if (*undo) { return buf_page_get_gen( page_id_t(rseg->space->id, (*undo)->last_page_no), - univ_page_size, RW_X_LATCH, + 0, RW_X_LATCH, buf_pool_is_obsolete((*undo)->withdraw_clock) ? NULL : (*undo)->guess_block, BUF_GET, __FILE__, __LINE__, mtr, err); From f4f8dd69aa373d7418a4148ac9eaf20e55da5a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 7 Feb 2019 16:25:18 +0200 Subject: [PATCH 45/91] MDEV-18493: Correct a bogus assertion --- storage/innobase/buf/buf0buf.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index e6957e43b22..d82cd9b829b 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -4889,7 +4889,7 @@ buf_page_optimistic_get( buf_page_make_young_if_needed(&block->page); ut_ad(!ibuf_inside(mtr) - || ibuf_page(block->page.id, block->physical_size(), NULL)); + || ibuf_page(block->page.id, block->zip_size(), NULL)); mtr_memo_type_t fix_type; From 59028d49eb92bc875c9fd243f9a6bf1796c78bb9 Mon Sep 17 00:00:00 2001 From: mkaruza Date: Thu, 7 Feb 2019 13:18:22 +0100 Subject: [PATCH 46/91] Fix for certification failure on galera.galera_sst_mysqldump Test galera_sst_mysqldump could fail occasionally due certification failure. Enforcing stricter causality checks by removing wsrep_sync_wait=0 from test configuration. --- mysql-test/suite/galera/t/galera_sst_mysqldump.cnf | 2 -- 1 file changed, 2 deletions(-) diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf index 0d05038f2fb..af4fedf12ce 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump.cnf @@ -5,7 +5,5 @@ [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' -wsrep_sync_wait=0 [mysqld.2] wsrep_provider_options='base_port=@mysqld.2.#galera_port;gcache.size=1;pc.ignore_sb=true' -wsrep_sync_wait=0 From 26dcf102e3b29e4b038aba5ce49b11a1b5ee8390 Mon Sep 17 00:00:00 2001 From: mkaruza Date: Tue, 5 Feb 2019 19:37:20 +0100 Subject: [PATCH 47/91] Extend mariabackup archive timestamp in SST script During parallel execution mariabackup script can fail when trying to create archive because of non unique name. Extending archive timestamp with nanosecond. --- scripts/wsrep_sst_mariabackup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index 5362389a59d..1e018f1a515 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -753,8 +753,8 @@ else if [[ "$sstlogarchive" -eq 1 ]] then - ARCHIVETIMESTAMP=$(date "+%Y.%m.%d-%H.%M.%S") - newfile="" + ARCHIVETIMESTAMP=$(date "+%Y.%m.%d-%H.%M.%S.%N") + newfile="" if [[ ! -z "$sstlogarchivedir" ]] then From accc7f6029a89ec079177b7aef1d153a23fa9561 Mon Sep 17 00:00:00 2001 From: mkaruza Date: Tue, 11 Dec 2018 14:39:18 +0100 Subject: [PATCH 48/91] MDEV-18178 Galera test failure on galera_sst_rsync2 * Donor node will now provide binlog-index argument to wsrep_sst_rsync script if binlog is used. * Write correct path and binlog file names into joiner binlog-index file --- mysql-test/suite/galera/disabled.def | 1 - .../suite/galera/r/galera_sst_rsync2.result | 2 ++ scripts/wsrep_sst_rsync.sh | 23 ++++++++++--------- sql/wsrep_sst.cc | 17 ++++++++++++-- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 4fe68a794fd..0ad0327f6fc 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -51,7 +51,6 @@ galera.galera_var_reject_queries : assertion in inline_mysql_socket_send query_cache : MDEV-18137: Galera test failure on query_cache galera.galera_autoinc_sst_mariabackup : MDEV-18177 Galera test failure on galera_autoinc_sst_mariabackup galera.galera_ist_mariabackup : Leaves port open -galera.galera_sst_rsync2 : MDEV-18178 Galera test failure on galera_sst_rsync2 galera.galera_kill_largechanges : MDEV-18179 Galera test failure on galera.galera_kill_largechanges galera.galera_concurrent_ctas : MDEV-18180 Galera test failure on galera.galera_concurrent_ctas galera.galera_var_retry_autocommit: MDEV-18181 Galera test failure on galera.galera_var_retry_autocommit diff --git a/mysql-test/suite/galera/r/galera_sst_rsync2.result b/mysql-test/suite/galera/r/galera_sst_rsync2.result index ff85a7d6c0f..d41d0d34e75 100644 --- a/mysql-test/suite/galera/r/galera_sst_rsync2.result +++ b/mysql-test/suite/galera/r/galera_sst_rsync2.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; connection node_1; connection node_2; Performing State Transfer on a server that has been shut down cleanly and restarted diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 1fecb6f09d9..6a71d7bbfb3 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -147,6 +147,7 @@ if ! [ -z $WSREP_SST_OPT_BINLOG_INDEX ] then BINLOG_INDEX_DIRNAME=$(dirname $WSREP_SST_OPT_BINLOG_INDEX) BINLOG_INDEX_FILENAME=$(basename $WSREP_SST_OPT_BINLOG_INDEX) + BINLOG_INDEX_FILENAME=${BINLOG_INDEX_FILENAME%.index}.index fi WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} @@ -268,12 +269,12 @@ EOF OLD_PWD="$(pwd)" cd $BINLOG_DIRNAME - if ! [ -z $WSREP_SST_OPT_BINLOG_INDEX ] + if [ -z $WSREP_SST_OPT_BINLOG_INDEX ] then - binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_FILENAME}.index) + binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_FILENAME}.index) else - cd $BINLOG_INDEX_DIRNAME - binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_INDEX_FILENAME}.index) + cd $BINLOG_INDEX_DIRNAME + binlog_files_full=$(tail -n $BINLOG_N_FILES ${BINLOG_INDEX_FILENAME}) fi cd $BINLOG_DIRNAME @@ -510,16 +511,16 @@ EOF # Clean up old binlog files first rm -f ${BINLOG_FILENAME}.* wsrep_log_info "Extracting binlog files:" - tar -xvf $BINLOG_TAR_FILE >&2 - for ii in $(ls -1 ${BINLOG_FILENAME}.*) - do - if ! [ -z $WSREP_SST_OPT_BINLOG_INDEX ] + tar -xvf $BINLOG_TAR_FILE >> _binlog_tmp_files_$! + while read bin_file; do + if [ -z $WSREP_SST_OPT_BINLOG_INDEX ] then - echo ${BINLOG_DIRNAME}/${ii} >> ${BINLOG_FILENAME}.index + echo ${BINLOG_DIRNAME}/${bin_file} >> ${BINLOG_FILENAME}.index else - echo ${BINLOG_DIRNAME}/${ii} >> ${BINLOG_INDEX_DIRNAME}/${BINLOG_INDEX_FILENAME}.index + echo ${BINLOG_DIRNAME}/${bin_file} >> ${BINLOG_INDEX_DIRNAME}/${BINLOG_INDEX_FILENAME} fi - done + done < _binlog_tmp_files_$! + rm -f _binlog_tmp_files_$! fi cd "$OLD_PWD" diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index afbcd4d6c52..103afa1c412 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -337,7 +337,8 @@ static int generate_binlog_index_opt_val(char** ret) { DBUG_ASSERT(ret); *ret= NULL; - if (opt_binlog_index_name) { + if (opt_bin_log) + { *ret= strcmp(opt_binlog_index_name, "0") ? my_strdup(opt_binlog_index_name, MYF(0)) : my_strdup("", MYF(0)); } @@ -1293,7 +1294,9 @@ static int sst_donate_other (const char* method, } const char* binlog_opt= ""; + const char* binlog_index_opt= ""; char* binlog_opt_val= NULL; + char* binlog_index_opt_val= NULL; int ret; if ((ret= generate_binlog_opt_val(&binlog_opt_val))) @@ -1301,7 +1304,15 @@ static int sst_donate_other (const char* method, WSREP_ERROR("sst_donate_other(): generate_binlog_opt_val() failed: %d",ret); return ret; } + + if ((ret= generate_binlog_index_opt_val(&binlog_index_opt_val))) + { + WSREP_ERROR("sst_prepare_other(): generate_binlog_index_opt_val() failed %d", + ret); + } + if (strlen(binlog_opt_val)) binlog_opt= WSREP_SST_OPT_BINLOG; + if (strlen(binlog_index_opt_val)) binlog_index_opt= WSREP_SST_OPT_BINLOG_INDEX; make_wsrep_defaults_file(); @@ -1315,15 +1326,18 @@ static int sst_donate_other (const char* method, WSREP_SST_OPT_DATA " '%s' " " %s " " %s '%s' " + " %s '%s' " WSREP_SST_OPT_GTID " '%s:%lld' " WSREP_SST_OPT_GTID_DOMAIN_ID " '%d'" "%s", method, addr, mysqld_unix_port, mysql_real_data_home, wsrep_defaults_file, binlog_opt, binlog_opt_val, + binlog_index_opt, binlog_index_opt_val, uuid_oss.str().c_str(), gtid.seqno().get(), wsrep_gtid_domain_id, bypass ? " " WSREP_SST_OPT_BYPASS : ""); my_free(binlog_opt_val); + my_free(binlog_index_opt_val); if (ret < 0 || ret >= cmd_len) { @@ -1397,4 +1411,3 @@ int wsrep_sst_donate(const std::string& msg, return (ret >= 0 ? 0 : 1); } - From 131a4680c70a387d05e0b9f7c7edf1f056024f38 Mon Sep 17 00:00:00 2001 From: mkaruza Date: Fri, 8 Feb 2019 11:58:00 +0100 Subject: [PATCH 49/91] Fixed and re-recorded tests for galera Re-recorded: galera.galera_gcache_recover_manytrx Fixed: galera_3nodes.galera_evs_suspect_timeout --- mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result | 2 ++ .../suite/galera_3nodes/r/galera_evs_suspect_timeout.result | 1 - .../suite/galera_3nodes/t/galera_evs_suspect_timeout.test | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result b/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result index 604b24a8fab..a0a45446eff 100644 --- a/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result +++ b/mysql-test/suite/galera/r/galera_gcache_recover_manytrx.result @@ -1,3 +1,5 @@ +connection node_2; +connection node_1; SET SESSION wsrep_sync_wait = 0; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY AUTO_INCREMENT, f2 LONGBLOB) ENGINE=InnoDB; CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB; diff --git a/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result b/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result index d612e9377a9..3543feff78c 100644 --- a/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result +++ b/mysql-test/suite/galera_3nodes/r/galera_evs_suspect_timeout.result @@ -25,5 +25,4 @@ COUNT(*) = 1 DROP TABLE t1; connection node_3; Resuming node ... -connection node_3; CALL mtr.add_suppression("WSREP: gcs_caused() returned -1 \\(Operation not permitted\\)"); diff --git a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test index aa733442b92..a4767928681 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test +++ b/mysql-test/suite/galera_3nodes/t/galera_evs_suspect_timeout.test @@ -56,8 +56,8 @@ DROP TABLE t1; # Reconnect node #3 so that MTR's end-of-test checks can run ---source include/galera_resume.inc --connection node_3 +--source include/galera_resume.inc --source include/wait_until_connected_again.inc --disable_query_log From 58de2bf30d5d736ca86fc6af78f772409b6f3d08 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Fri, 8 Feb 2019 14:17:23 +0000 Subject: [PATCH 50/91] MDEV-18481 Use mlog_memset() to clear wsrep checkpoint --- storage/innobase/trx/trx0rseg.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 239df440c2b..f57e97b2e57 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -98,6 +98,19 @@ trx_rseg_update_wsrep_checkpoint( trx_rseg_write_wsrep_checkpoint(rseg_header, xid, mtr); } +/** Clear the WSREP XID information from rollback segment header. +@param[in,out] rseg_header Rollback segment header +@param[in,out] mtr mini-transaction */ +static void +trx_rseg_clear_wsrep_checkpoint( + trx_rsegf_t* rseg_header, + mtr_t* mtr) +{ + mlog_memset(rseg_header + TRX_RSEG_WSREP_XID_INFO, + TRX_RSEG_WSREP_XID_DATA + XIDDATASIZE + - TRX_RSEG_WSREP_XID_INFO, 0, mtr); +} + /** Update WSREP checkpoint XID in first rollback segment header as part of wsrep_set_SE_checkpoint() when it is guaranteed that there are no wsrep transactions committing. @@ -128,10 +141,6 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) trx_rseg_update_wsrep_checkpoint(rseg_header, xid, &mtr); if (must_clear_rsegs) { - XID null_xid; - memset(&null_xid, 0, sizeof null_xid); - null_xid.null(); - memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); /* Because the UUID part of the WSREP XID differed from current_xid_uuid, the WSREP group UUID was changed, and we must reset the XID in all rollback @@ -139,11 +148,10 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) for (ulint rseg_id = 1; rseg_id < TRX_SYS_N_RSEGS; ++rseg_id) { if (const trx_rseg_t* rseg = trx_sys.rseg_array[rseg_id]) { - trx_rseg_write_wsrep_checkpoint( + trx_rseg_clear_wsrep_checkpoint( trx_rsegf_get(rseg->space, rseg->page_no, &mtr), - &null_xid, &mtr); } } From b8e867e8692177cd2b9371f6ebcb4ab219977962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 8 Feb 2019 18:45:00 +0200 Subject: [PATCH 51/91] MDEV-18219 Assertion index->n_core_null_bytes <= ... after DROP COLUMN rec_init_offsets(): Relax a debug assertion that is too strict during the execution of btr_cur_instant_init_low(). --- .../suite/innodb/r/instant_alter_bugs.result | 29 +++++++++++++++++ .../suite/innodb/t/instant_alter_bugs.test | 31 +++++++++++++++++++ storage/innobase/rem/rem0rec.cc | 8 ++++- 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/r/instant_alter_bugs.result b/mysql-test/suite/innodb/r/instant_alter_bugs.result index 7326b9b7c6e..5284d021c67 100644 --- a/mysql-test/suite/innodb/r/instant_alter_bugs.result +++ b/mysql-test/suite/innodb/r/instant_alter_bugs.result @@ -146,3 +146,32 @@ check table t; Table Op Msg_type Msg_text test.t check status OK drop table t; +# +# MDEV-18219 Assertion `index->n_core_null_bytes <= ...' failed +# in rec_init_offsets after instant DROP COLUMN +# +CREATE TABLE t1 (a INT, b INT NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(0,9),(2,7),(3,1),(3,4),(8,4),(3,7),(6,1),(3,8),(1,2),(4,1),(0,8),(5,3), +(1,3),(1,6),(2,1),(8,7),(6,0),(1,9),(9,4),(0,6),(9,3),(0,9),(9,4),(2,4), +(2,7),(7,8),(8,2),(2,5),(6,1),(4,5),(5,3),(6,8),(4,9),(5,7),(7,5),(5,1), +(8,8),(5,7),(3,8),(0,1),(8,4),(8,3),(9,7),(4,8),(1,1),(0,4),(2,6),(8,5), +(8,8),(8,7),(6,7),(1,7),(9,6),(3,6),(1,9),(0,3),(5,3),(2,4),(0,6),(2,0), +(6,5),(1,6),(2,4),(9,1),(3,0),(6,4),(1,3),(0,8),(3,5),(3,1),(8,9),(9,9), +(7,9),(4,5),(2,2),(3,8),(0,8),(7,1),(2,0),(1,5),(7,3),(4,4),(3,9),(7,2), +(6,2),(0,4),(2,0),(1,5),(5,7),(4,5),(3,7),(6,0),(2,1),(5,0),(1,0),(2,0), +(8,4),(5,7),(3,5),(0,5),(7,6),(5,9),(1,2),(4,2),(8,5),(8,7),(2,8),(1,8), +(4,3),(1,6),(7,8),(3,7),(4,6),(1,1),(3,0),(1,6),(2,0),(3,4),(4,8),(3,9), +(8,0),(4,9),(4,0),(3,9),(6,4),(7,4),(5,8),(4,7),(7,3),(5,9),(2,3),(7,3), +(0,4),(5,9),(9,8),(4,2),(3,6),(2,6),(1,8),(7,0),(0,0),(2,3),(1,2),(3,3), +(2,7),(6,0),(9,0),(6,9),(4,6),(9,8),(0,7),(9,1),(9,6),(4,3),(7,7),(7,7), +(4,1),(4,7),(7,3),(2,8),(5,8),(8,9),(3,9),(7,7),(0,8),(4,9),(3,2),(5,0), +(1,7),(0,3),(2,9),(9,7),(7,5),(6,9),(8,5),(3,6),(1,1),(2,8),(7,9),(4,9), +(6,6),(5,9),(5,3),(9,8),(3,3),(5,6),(0,9),(3,9),(7,9),(7,3),(5,2),(1,4), +(4,4),(8,2),(2,2),(8,3),(9,1),(4,9),(9,8),(1,8),(1,8),(9,1),(1,1),(3,0), +(4,6),(9,3),(3,3),(5,2),(0,1),(3,4),(3,2),(1,3),(4,4),(7,0),(4,6),(7,2), +(4,5),(8,7),(7,8),(8,1),(3,5),(0,6),(3,5),(2,1),(4,4),(3,4),(2,1),(4,1); +INSERT INTO t1 SELECT * FROM t1; +ALTER TABLE t1 DROP a; +ALTER TABLE t1 ADD vb INT AS (b) VIRTUAL; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/instant_alter_bugs.test b/mysql-test/suite/innodb/t/instant_alter_bugs.test index 07d7db68c22..7b7ba44f09b 100644 --- a/mysql-test/suite/innodb/t/instant_alter_bugs.test +++ b/mysql-test/suite/innodb/t/instant_alter_bugs.test @@ -154,3 +154,34 @@ alter table t modify c int without system versioning, algorithm=instant; set @@system_versioning_alter_history = error; check table t; drop table t; + +--echo # +--echo # MDEV-18219 Assertion `index->n_core_null_bytes <= ...' failed +--echo # in rec_init_offsets after instant DROP COLUMN +--echo # +CREATE TABLE t1 (a INT, b INT NOT NULL) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(0,9),(2,7),(3,1),(3,4),(8,4),(3,7),(6,1),(3,8),(1,2),(4,1),(0,8),(5,3), +(1,3),(1,6),(2,1),(8,7),(6,0),(1,9),(9,4),(0,6),(9,3),(0,9),(9,4),(2,4), +(2,7),(7,8),(8,2),(2,5),(6,1),(4,5),(5,3),(6,8),(4,9),(5,7),(7,5),(5,1), +(8,8),(5,7),(3,8),(0,1),(8,4),(8,3),(9,7),(4,8),(1,1),(0,4),(2,6),(8,5), +(8,8),(8,7),(6,7),(1,7),(9,6),(3,6),(1,9),(0,3),(5,3),(2,4),(0,6),(2,0), +(6,5),(1,6),(2,4),(9,1),(3,0),(6,4),(1,3),(0,8),(3,5),(3,1),(8,9),(9,9), +(7,9),(4,5),(2,2),(3,8),(0,8),(7,1),(2,0),(1,5),(7,3),(4,4),(3,9),(7,2), +(6,2),(0,4),(2,0),(1,5),(5,7),(4,5),(3,7),(6,0),(2,1),(5,0),(1,0),(2,0), +(8,4),(5,7),(3,5),(0,5),(7,6),(5,9),(1,2),(4,2),(8,5),(8,7),(2,8),(1,8), +(4,3),(1,6),(7,8),(3,7),(4,6),(1,1),(3,0),(1,6),(2,0),(3,4),(4,8),(3,9), +(8,0),(4,9),(4,0),(3,9),(6,4),(7,4),(5,8),(4,7),(7,3),(5,9),(2,3),(7,3), +(0,4),(5,9),(9,8),(4,2),(3,6),(2,6),(1,8),(7,0),(0,0),(2,3),(1,2),(3,3), +(2,7),(6,0),(9,0),(6,9),(4,6),(9,8),(0,7),(9,1),(9,6),(4,3),(7,7),(7,7), +(4,1),(4,7),(7,3),(2,8),(5,8),(8,9),(3,9),(7,7),(0,8),(4,9),(3,2),(5,0), +(1,7),(0,3),(2,9),(9,7),(7,5),(6,9),(8,5),(3,6),(1,1),(2,8),(7,9),(4,9), +(6,6),(5,9),(5,3),(9,8),(3,3),(5,6),(0,9),(3,9),(7,9),(7,3),(5,2),(1,4), +(4,4),(8,2),(2,2),(8,3),(9,1),(4,9),(9,8),(1,8),(1,8),(9,1),(1,1),(3,0), +(4,6),(9,3),(3,3),(5,2),(0,1),(3,4),(3,2),(1,3),(4,4),(7,0),(4,6),(7,2), +(4,5),(8,7),(7,8),(8,1),(3,5),(0,6),(3,5),(2,1),(4,4),(3,4),(2,1),(4,1); +INSERT INTO t1 SELECT * FROM t1; +ALTER TABLE t1 DROP a; +# Exploit MDEV-17468 to force the table definition to be reloaded +ALTER TABLE t1 ADD vb INT AS (b) VIRTUAL; +DROP TABLE t1; diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 19764318c1a..c76bf3429b9 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -612,7 +612,13 @@ rec_init_offsets( ulint i = 0; ulint offs; - ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable)); + /* This assertion was relaxed for the btr_cur_open_at_index_side() + call in btr_cur_instant_init_low(). We cannot invoke + index->is_instant(), because the same assertion would fail there + until btr_cur_instant_init_low() has invoked + dict_table_t::deserialise_columns(). */ + ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable) + || (!leaf && index->n_core_fields != index->n_fields)); ut_d(offsets[2] = ulint(rec)); ut_d(offsets[3] = ulint(index)); From ea25bdc135d226db9ffa20d5aed9e12e6ea9c6fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 8 Feb 2019 19:10:33 +0200 Subject: [PATCH 52/91] Do not write MLOG_IBUF_BITMAP_INIT Use ibuf_bitmap_page_init() only during recovery. fsp_fill_free_list(): Initialize the FIL_PAGE_TYPE using MLOG_2BYTES. The page contents will already have been zeroed out by MLOG_INIT_FILE_PAGE2. ibuf_bitmap_init_apply(): Replaces ibuf_parse_bitmap_init(). --- storage/innobase/fsp/fsp0fsp.cc | 6 ++--- storage/innobase/ibuf/ibuf0ibuf.cc | 33 ++-------------------------- storage/innobase/include/ibuf0ibuf.h | 19 ++-------------- storage/innobase/include/mtr0types.h | 4 ++-- storage/innobase/log/log0recv.cc | 2 +- 5 files changed, 10 insertions(+), 54 deletions(-) diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 2aed55db256..cd0454d0cca 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -1065,9 +1065,9 @@ fsp_fill_free_list( buf_block_dbg_add_level(block, SYNC_FSP_PAGE); fsp_init_file_page(space, block, &ibuf_mtr); - - ibuf_bitmap_page_init(block, &ibuf_mtr); - + mlog_write_ulint(block->frame + FIL_PAGE_TYPE, + FIL_PAGE_IBUF_BITMAP, + MLOG_2BYTES, &ibuf_mtr); mtr_commit(&ibuf_mtr); } } diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index dd60d5c8096..429163528ff 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -584,13 +584,8 @@ ibuf_max_size_update( } -/*********************************************************************//** -Initializes an ibuf bitmap page. */ -void -ibuf_bitmap_page_init( -/*==================*/ - buf_block_t* block, /*!< in: bitmap page */ - mtr_t* mtr) /*!< in: mtr */ +/** Apply MLOG_IBUF_BITMAP_INIT when crash-upgrading */ +ATTRIBUTE_COLD void ibuf_bitmap_init_apply(buf_block_t* block) { page_t* page; ulint byte_offset; @@ -605,30 +600,6 @@ ibuf_bitmap_page_init( * IBUF_BITS_PER_PAGE); memset(page + IBUF_BITMAP, 0, byte_offset); - - /* The remaining area (up to the page trailer) is uninitialized. */ - mlog_write_initial_log_record(page, MLOG_IBUF_BITMAP_INIT, mtr); -} - -/*********************************************************************//** -Parses a redo log record of an ibuf bitmap page init. -@return end of log record or NULL */ -byte* -ibuf_parse_bitmap_init( -/*===================*/ - byte* ptr, /*!< in: buffer */ - byte* end_ptr MY_ATTRIBUTE((unused)), /*!< in: buffer end */ - buf_block_t* block, /*!< in: block or NULL */ - mtr_t* mtr) /*!< in: mtr or NULL */ -{ - ut_ad(ptr != NULL); - ut_ad(end_ptr != NULL); - - if (block) { - ibuf_bitmap_page_init(block, mtr); - } - - return(ptr); } # ifdef UNIV_DEBUG diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 595ce5a8fed..c0c19eedab9 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -119,13 +119,6 @@ ibuf_mtr_commit( /*============*/ mtr_t* mtr) /*!< in/out: mini-transaction */ MY_ATTRIBUTE((nonnull)); -/*********************************************************************//** -Initializes an ibuf bitmap page. */ -void -ibuf_bitmap_page_init( -/*==================*/ - buf_block_t* block, /*!< in: bitmap page */ - mtr_t* mtr); /*!< in: mtr */ /************************************************************************//** Resets the free bits of the page in the ibuf bitmap. This is done in a separate mini-transaction, hence this operation does not restrict @@ -372,16 +365,8 @@ ibuf_merge_space( /*=============*/ ulint space); /*!< in: space id */ -/*********************************************************************//** -Parses a redo log record of an ibuf bitmap page init. -@return end of log record or NULL */ -byte* -ibuf_parse_bitmap_init( -/*===================*/ - byte* ptr, /*!< in: buffer */ - byte* end_ptr,/*!< in: buffer end */ - buf_block_t* block, /*!< in: block or NULL */ - mtr_t* mtr); /*!< in: mtr or NULL */ +/** Apply MLOG_IBUF_BITMAP_INIT when crash-upgrading */ +ATTRIBUTE_COLD void ibuf_bitmap_init_apply(buf_block_t* block); #ifdef UNIV_IBUF_COUNT_DEBUG /** Gets the ibuf count for a given page. diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h index 39ed707267d..20962f83020 100644 --- a/storage/innobase/include/mtr0types.h +++ b/storage/innobase/include/mtr0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -118,7 +118,7 @@ enum mlog_id_t { /** mark an index record as the predefined minimum record */ MLOG_REC_MIN_MARK = 26, - /** initialize an ibuf bitmap page */ + /** initialize an ibuf bitmap page (used in MariaDB 10.2 and 10.3) */ MLOG_IBUF_BITMAP_INIT = 27, #ifdef UNIV_LOG_LSN_DEBUG diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 9b7866c3d1a..eaf0434dd31 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1516,7 +1516,7 @@ parse_log: break; case MLOG_IBUF_BITMAP_INIT: /* Allow anything in page_type when creating a page. */ - ptr = ibuf_parse_bitmap_init(ptr, end_ptr, block, mtr); + if (block) ibuf_bitmap_init_apply(block); break; case MLOG_INIT_FILE_PAGE2: /* Allow anything in page_type when creating a page. */ From 3c305d3f1951f1667f84e48ddd98674c6318c39d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 8 Feb 2019 19:15:44 +0200 Subject: [PATCH 53/91] MDEV-15528: Introduce MLOG_INIT_FREE_PAGE This is only a placeholder that allows an implementation later during the development of MariaDB, so that downgrade to an earlier version (with this code) will be possible. We want to be able to zero out freed pages to reduce write amplification, and to scrub old data. Zeroing out the pages is optional, not mandatory for correctness. After all, the MLOG_INIT_FREE_PAGE record can only be emitted for pages that are marked free in the allocation bitmap page. --- storage/innobase/include/mtr0types.h | 5 ++++- storage/innobase/log/log0recv.cc | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h index 20962f83020..af42010f415 100644 --- a/storage/innobase/include/mtr0types.h +++ b/storage/innobase/include/mtr0types.h @@ -231,8 +231,11 @@ enum mlog_id_t { /** initialize a page with a string of identical bytes */ MLOG_MEMSET = 63, + /** Zero-fill a page that is not allocated. */ + MLOG_INIT_FREE_PAGE = 64, + /** biggest value (used in assertions) */ - MLOG_BIGGEST_TYPE = MLOG_MEMSET, + MLOG_BIGGEST_TYPE = MLOG_INIT_FREE_PAGE, /** log record for writing/updating crypt data of a tablespace */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index eaf0434dd31..f59bee021a1 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -1522,6 +1522,11 @@ parse_log: /* Allow anything in page_type when creating a page. */ ptr = fsp_parse_init_file_page(ptr, end_ptr, block); break; + case MLOG_INIT_FREE_PAGE: + /* The page can be zero-filled and its previous + contents can be ignored. We do not write or apply + this record yet. */ + break; case MLOG_WRITE_STRING: ptr = mlog_parse_string(ptr, end_ptr, page, page_zip); break; @@ -3861,6 +3866,9 @@ static const char* get_mlog_string(mlog_id_t type) case MLOG_MEMSET: return("MLOG_MEMSET"); + case MLOG_INIT_FREE_PAGE: + return("MLOG_INIT_FREE_PAGE"); + case MLOG_FILE_WRITE_CRYPT_DATA: return("MLOG_FILE_WRITE_CRYPT_DATA"); } From d11be23933def394585fae83a6f1ab561e3736f2 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 9 Feb 2019 22:54:26 -0800 Subject: [PATCH 54/91] MDEV-17096 Pushdown of simple derived tables to storage engines Resolved the problem of forming a proper query string for FEDERATEDX. Added test cases. Cleanup of extra spaces. --- .../federatedx_create_handlers.result | 119 +++++++++++++++++- .../federated/federatedx_create_handlers.test | 60 +++++++-- sql/derived_handler.cc | 8 +- sql/item_cmpfunc.cc | 9 +- sql/item_subselect.cc | 6 +- sql/mysqld.h | 2 + sql/select_handler.cc | 14 +-- sql/select_handler.h | 10 +- sql/sql_derived.cc | 34 +++-- sql/sql_explain.cc | 6 +- sql/sql_select.cc | 8 +- sql/table.h | 1 + storage/federatedx/federatedx_pushdown.cc | 19 ++- storage/federatedx/federatedx_pushdown.h | 4 +- 14 files changed, 233 insertions(+), 67 deletions(-) diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result index fdad44c1b95..a25b0191e55 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.result +++ b/mysql-test/suite/federated/federatedx_create_handlers.result @@ -10,7 +10,7 @@ Warnings: Note 1051 Unknown table 'federated.t1' CREATE TABLE federated.t1 ( id int(20) NOT NULL, -name varchar(16) NOT NULL default '' +name varchar(16) NOT NULL default '' ) DEFAULT CHARSET=latin1; INSERT INTO federated.t1 VALUES @@ -19,7 +19,7 @@ DROP TABLE IF EXISTS federated.t2; Warnings: Note 1051 Unknown table 'federated.t2' CREATE TABLE federated.t2 ( -name varchar(16) NOT NULL default '' +name varchar(16) NOT NULL default '' ) DEFAULT CHARSET=latin1; INSERT INTO federated.t2 VALUES @@ -30,7 +30,7 @@ Warnings: Note 1051 Unknown table 'federated.t1' CREATE TABLE federated.t1 ( id int(20) NOT NULL, -name varchar(16) NOT NULL default '' +name varchar(16) NOT NULL default '' ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; @@ -38,7 +38,7 @@ DROP TABLE IF EXISTS federated.t2; Warnings: Note 1051 Unknown table 'federated.t2' CREATE TABLE federated.t2 ( -name varchar(16) NOT NULL default '' +name varchar(16) NOT NULL default '' ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t2'; @@ -123,7 +123,7 @@ ANALYZE } } CREATE TABLE federated.t3 ( -name varchar(16) NOT NULL default '' +name varchar(16) NOT NULL default '' ) DEFAULT CHARSET=latin1; INSERT INTO federated.t3 VALUES @@ -190,7 +190,114 @@ id select_type table type possible_keys key key_len ref rows r_rows filtered r_f 1 PRIMARY t3 ALL NULL NULL NULL NULL 7 7.00 100.00 100.00 1 PRIMARY ref key0 key0 18 federated.t3.name 2 0.00 100.00 100.00 2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL -DROP TABLE federated.t1, federated.t2; +SELECT * +FROM federated.t3, (SELECT t1.name FROM federated.t1 +WHERE id IN (SELECT count(*) +FROM federated.t2 GROUP BY name)) t +WHERE federated.t3.name=t.name; +name name +xxx xxx +EXPLAIN +SELECT * +FROM federated.t3, (SELECT t1.name FROM federated.t1 +WHERE id IN (SELECT count(*) +FROM federated.t2 GROUP BY name)) t +WHERE federated.t3.name=t.name; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 7 +1 PRIMARY ref key0 key0 18 federated.t3.name 2 +2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL +3 MATERIALIZED t2 ALL NULL NULL NULL NULL 7 Using temporary +ANALYZE FORMAT=JSON +SELECT * +FROM federated.t3, (SELECT t1.name FROM federated.t1 +WHERE id IN (SELECT count(*) +FROM federated.t2 GROUP BY name)) t +WHERE federated.t3.name=t.name; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "table": { + "table_name": "t3", + "access_type": "ALL", + "r_loops": 1, + "rows": 7, + "r_rows": 7, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + }, + "table": { + "table_name": "", + "access_type": "ref", + "possible_keys": ["key0"], + "key": "key0", + "key_length": "18", + "used_key_parts": ["name"], + "ref": ["federated.t3.name"], + "r_loops": 7, + "rows": 2, + "r_rows": 0, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100, + "materialized": { + "query_block": { + "select_id": 2, + "table": { + "message": "Pushed derived" + }, + "subqueries": [ + { + "query_block": { + "select_id": 3, + "temporary_table": { + "table": { + "table_name": "t2", + "access_type": "ALL", + "r_loops": 0, + "rows": 7, + "r_rows": null, + "filtered": 100, + "r_filtered": null + } + } + } + } + ] + } + } + } + } +} +SELECT t.id, federated.t3.name +FROM federated.t3, +( SELECT * FROM federated.t1 WHERE id < 3 +UNION +SELECT * FROM federated.t1 WHERE id >= 5) t +WHERE federated.t3.name=t.name; +id name +5 yyy +7 yyy +5 yyy +7 yyy +5 yyy +7 yyy +EXPLAIN +SELECT t.id, federated.t3.name +FROM federated.t3, +( SELECT * FROM federated.t1 WHERE id < 3 +UNION +SELECT * FROM federated.t1 WHERE id >= 5) t +WHERE federated.t3.name=t.name; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t3 ALL NULL NULL NULL NULL 7 +1 PRIMARY ref key0 key0 18 federated.t3.name 2 +2 PUSHED DERIVED NULL NULL NULL NULL NULL NULL NULL NULL +DROP TABLE federated.t1, federated.t2, federated.t3; connection slave; DROP TABLE federated.t1, federated.t2; connection default; diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test index 0e586dad0c1..21539b61c8a 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.test +++ b/mysql-test/suite/federated/federatedx_create_handlers.test @@ -7,7 +7,7 @@ DROP TABLE IF EXISTS federated.t1; CREATE TABLE federated.t1 ( id int(20) NOT NULL, - name varchar(16) NOT NULL default '' + name varchar(16) NOT NULL default '' ) DEFAULT CHARSET=latin1; @@ -17,7 +17,7 @@ INSERT INTO federated.t1 VALUES DROP TABLE IF EXISTS federated.t2; CREATE TABLE federated.t2 ( - name varchar(16) NOT NULL default '' + name varchar(16) NOT NULL default '' ) DEFAULT CHARSET=latin1; @@ -33,7 +33,7 @@ DROP TABLE IF EXISTS federated.t1; eval CREATE TABLE federated.t1 ( id int(20) NOT NULL, - name varchar(16) NOT NULL default '' + name varchar(16) NOT NULL default '' ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; @@ -43,7 +43,7 @@ DROP TABLE IF EXISTS federated.t2; --replace_result $SLAVE_MYPORT SLAVE_PORT eval CREATE TABLE federated.t2 ( - name varchar(16) NOT NULL default '' + name varchar(16) NOT NULL default '' ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t2'; @@ -76,11 +76,12 @@ SELECT id FROM federated.t1 WHERE id < 5; ANALYZE SELECT id FROM federated.t1 WHERE id < 5; +--source include/analyze-format.inc ANALYZE FORMAT=JSON SELECT id FROM federated.t1 WHERE id < 5; CREATE TABLE federated.t3 ( - name varchar(16) NOT NULL default '' + name varchar(16) NOT NULL default '' ) DEFAULT CHARSET=latin1; @@ -89,26 +90,63 @@ INSERT INTO federated.t3 VALUES SELECT * FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t -WHERE federated.t3.name=t.name; +WHERE federated.t3.name=t.name; EXPLAIN SELECT * FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t -WHERE federated.t3.name=t.name; +WHERE federated.t3.name=t.name; EXPLAIN FORMAT=JSON SELECT * FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t -WHERE federated.t3.name=t.name; +WHERE federated.t3.name=t.name; ANALYZE SELECT * FROM federated.t3, (SELECT * FROM federated.t1 WHERE id > 3) t -WHERE federated.t3.name=t.name; +WHERE federated.t3.name=t.name; -DROP TABLE federated.t1, federated.t2; +SELECT * +FROM federated.t3, (SELECT t1.name FROM federated.t1 + WHERE id IN (SELECT count(*) + FROM federated.t2 GROUP BY name)) t +WHERE federated.t3.name=t.name; -connection slave; +EXPLAIN +SELECT * +FROM federated.t3, (SELECT t1.name FROM federated.t1 + WHERE id IN (SELECT count(*) + FROM federated.t2 GROUP BY name)) t +WHERE federated.t3.name=t.name; + +--source include/analyze-format.inc +ANALYZE FORMAT=JSON +SELECT * +FROM federated.t3, (SELECT t1.name FROM federated.t1 + WHERE id IN (SELECT count(*) + FROM federated.t2 GROUP BY name)) t +WHERE federated.t3.name=t.name; + +SELECT t.id, federated.t3.name +FROM federated.t3, + ( SELECT * FROM federated.t1 WHERE id < 3 + UNION + SELECT * FROM federated.t1 WHERE id >= 5) t +WHERE federated.t3.name=t.name; + +EXPLAIN +SELECT t.id, federated.t3.name +FROM federated.t3, + ( SELECT * FROM federated.t1 WHERE id < 3 + UNION + SELECT * FROM federated.t1 WHERE id >= 5) t +WHERE federated.t3.name=t.name; + + +DROP TABLE federated.t1, federated.t2, federated.t3; + +connection slave; DROP TABLE federated.t1, federated.t2; connection default; diff --git a/sql/derived_handler.cc b/sql/derived_handler.cc index 561c18a5657..1fa5e94a1d4 100644 --- a/sql/derived_handler.cc +++ b/sql/derived_handler.cc @@ -16,7 +16,7 @@ void derived_handler::set_derived(TABLE_LIST *tbl) Pushdown_derived::Pushdown_derived(TABLE_LIST *tbl, derived_handler *h) : derived(tbl), handler(h) -{ +{ is_analyze= handler->thd->lex->analyze_stmt; } @@ -42,7 +42,7 @@ int Pushdown_derived::execute() handler->end_scan(); DBUG_RETURN(0); } - + while (!(err= handler->next_row())) { if (unlikely(thd->check_killed())) @@ -50,7 +50,7 @@ int Pushdown_derived::execute() handler->end_scan(); DBUG_RETURN(-1); } - + if ((err= table->file->ha_write_tmp_row(table->record[0]))) { bool is_duplicate; @@ -81,4 +81,4 @@ error_2: handler->print_error(err, MYF(0)); DBUG_RETURN(-1); // Error not sent to client } - + diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 4cd63042558..821f51ffaf5 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1215,8 +1215,13 @@ bool Item_in_optimizer::eval_not_null_tables(void *opt_arg) void Item_in_optimizer::print(String *str, enum_query_type query_type) { - restore_first_argument(); - Item_func::print(str, query_type); + if (query_type & QT_PARSABLE) + args[1]->print(str, query_type); + else + { + restore_first_argument(); + Item_func::print(str, query_type); + } } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 0ace59fd2fc..7aa2ed489a3 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -3272,7 +3272,8 @@ out: void Item_in_subselect::print(String *str, enum_query_type query_type) { - if (test_strategy(SUBS_IN_TO_EXISTS)) + if (test_strategy(SUBS_IN_TO_EXISTS) && + !(query_type & QT_PARSABLE)) str->append(STRING_WITH_LEN("")); else { @@ -3499,7 +3500,8 @@ Item_allany_subselect::select_transformer(JOIN *join) void Item_allany_subselect::print(String *str, enum_query_type query_type) { - if (test_strategy(SUBS_IN_TO_EXISTS)) + if (test_strategy(SUBS_IN_TO_EXISTS) && + !(query_type & QT_PARSABLE)) str->append(STRING_WITH_LEN("")); else { diff --git a/sql/mysqld.h b/sql/mysqld.h index 3d056fb95c7..320dedc4671 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -745,6 +745,8 @@ enum enum_query_type /// SHOW CREATE {VIEW|PROCEDURE|FUNCTION} and other cases where the /// original representation is required, should set this flag. QT_ITEM_ORIGINAL_FUNC_NULLIF= (1 << 7), + /// good for parsing + QT_PARSABLE= (1 << 8), /// This value means focus on readability, not on ability to parse back, etc. QT_EXPLAIN= QT_TO_SYSTEM_CHARSET | diff --git a/sql/select_handler.cc b/sql/select_handler.cc index 17475f4907d..9a8d3914b21 100644 --- a/sql/select_handler.cc +++ b/sql/select_handler.cc @@ -6,7 +6,7 @@ Pushdown_select::Pushdown_select(SELECT_LEX *sel, select_handler *h) : select(sel), handler(h) -{ +{ is_analyze= handler->thd->lex->analyze_stmt; } @@ -35,7 +35,7 @@ bool Pushdown_select::init() DBUG_RETURN(true); if (handler->table->fill_item_list(&result_columns)) DBUG_RETURN(true); - DBUG_RETURN(false); + DBUG_RETURN(false); } bool Pushdown_select::send_result_set_metadata() @@ -74,7 +74,7 @@ bool Pushdown_select::send_data() protocol->remove_last_row(); DBUG_RETURN(true); } - + thd->inc_sent_row_count(1); if (thd->vio_ok()) @@ -88,13 +88,13 @@ bool Pushdown_select::send_eof() THD *thd= handler->thd; DBUG_ENTER("Pushdown_select::send_eof"); - /* + /* Don't send EOF if we're in error condition (which implies we've already sent or are sending an error) */ if (thd->is_error()) DBUG_RETURN(true); - ::my_eof(thd); + ::my_eof(thd); DBUG_RETURN(false); } @@ -113,10 +113,10 @@ int Pushdown_select::execute() handler->end_scan(); DBUG_RETURN(0); } - + if (send_result_set_metadata()) DBUG_RETURN(-1); - + while (!(err= handler->next_row())) { if (thd->check_killed() || send_data()) diff --git a/sql/select_handler.h b/sql/select_handler.h index 3b1347efed6..19a1883f6c7 100644 --- a/sql/select_handler.h +++ b/sql/select_handler.h @@ -20,9 +20,9 @@ class select_handler select_handler(THD *thd_arg, handlerton *ht_arg) : thd(thd_arg), ht(ht_arg), table(0) {} - - virtual ~select_handler() {} - + + virtual ~select_handler() {} + /* Functions to scan the select result set. All these returns 0 if ok, error code in case of error. @@ -32,7 +32,7 @@ class select_handler virtual int init_scan() = 0; /* - Put the next produced row of the result set in table->record[0] + Put the next produced row of the result set in table->record[0] and return 0. Return HA_ERR_END_OF_FILE if there are no more rows, return other error number in case of fatal error. */ @@ -40,7 +40,7 @@ class select_handler /* Finish scanning */ virtual int end_scan() = 0; - + /* Report errors */ virtual void print_error(int error, myf errflag) = 0; }; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 9ad22dde9c6..564049e59e1 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -385,7 +385,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_RETURN(FALSE); } - if ((derived->dt_handler= derived->find_derived_handler(thd))) + if (derived->dt_handler) { derived->change_refs_to_fields(); derived->set_materialized_derived(); @@ -820,6 +820,24 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) if (derived->is_derived() && derived->is_merged_derived()) first_select->mark_as_belong_to_derived(derived); + derived->dt_handler= derived->find_derived_handler(thd); + if (derived->dt_handler) + { + char query_buff[4096]; + String derived_query(query_buff, sizeof(query_buff), thd->charset()); + derived_query.length(0); + derived->derived->print(&derived_query, + enum_query_type(QT_VIEW_INTERNAL | + QT_ITEM_ORIGINAL_FUNC_NULLIF | + QT_PARSABLE)); + if (!thd->make_lex_string(&derived->derived_spec, + derived_query.ptr(), derived_query.length())) + { + delete derived->dt_handler; + derived->dt_handler= NULL; + } + } + exit: /* Hide "Unknown column" or "Unknown function" error */ if (derived->view) @@ -912,19 +930,17 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_RETURN(FALSE); } - if (derived->is_materialized_derived() && !derived->dt_handler) - derived->dt_handler= derived->find_derived_handler(thd); - if (derived->dt_handler) + if (derived->is_materialized_derived() && derived->dt_handler) { if (!(derived->pushdown_derived= new (thd->mem_root) Pushdown_derived(derived, derived->dt_handler))) { delete derived->dt_handler; - derived->dt_handler= NULL; - DBUG_RETURN(1); + derived->dt_handler= NULL; + DBUG_RETURN(TRUE); } - } - + } + lex->current_select= first_select; if (unit->is_unit_op()) @@ -1136,7 +1152,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) if (unit->executed) DBUG_RETURN(FALSE); res= derived->pushdown_derived->execute(); - unit->executed= true; + unit->executed= true; delete derived->pushdown_derived; DBUG_RETURN(res); } diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index b8d80c7c59c..7bb04fe6be4 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -339,7 +339,7 @@ int print_explain_row(select_result_sink *result, if (!select_type[0]) return 0; - + item_list.push_back(new (mem_root) Item_int(thd, (int32) select_number), mem_root); item_list.push_back(new (mem_root) Item_string_sys(thd, select_type), @@ -756,7 +756,7 @@ int Explain_select::print_explain(Explain_query *query, { print_explain_message_line(output, explain_flags, is_analyze, select_id /*select number*/, - select_type, + select_type, NULL, /* rows */ NULL); } @@ -1225,7 +1225,7 @@ int Explain_table_access::print_explain(select_result_sink *output, uint8 explai { THD *thd= output->thd; MEM_ROOT *mem_root= thd->mem_root; - + List item_list; Item *item_null= new (mem_root) Item_null(thd); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7cbbdfeee4f..e9040e197e0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -4044,7 +4044,7 @@ void JOIN::exec_inner() not the case. */ if (exec_const_order_group_cond.elements && - !(select_options & SELECT_DESCRIBE) && + !(select_options & SELECT_DESCRIBE) && !select_lex->pushdown_select) { List_iterator_fast const_item_it(exec_const_order_group_cond); @@ -4300,7 +4300,7 @@ mysql_select(THD *thd, DBUG_RETURN(TRUE); } } - + if ((err= join->optimize())) { goto err; // 1 @@ -4322,7 +4322,7 @@ mysql_select(THD *thd, select_lex->where= join->conds_history; select_lex->having= join->having_history; } - + err: if (select_lex->pushdown_select) @@ -25885,7 +25885,7 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) res= unit->exec(); } } - else + else { thd->lex->current_select= first; unit->set_limit(unit->global_parameters()); diff --git a/sql/table.h b/sql/table.h index 7b88344830b..f7bcdaa58b2 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2137,6 +2137,7 @@ struct TABLE_LIST bool is_derived_with_recursive_reference; bool block_handle_derived; derived_handler *dt_handler; + LEX_CSTRING derived_spec; Pushdown_derived *pushdown_derived; ST_SCHEMA_TABLE *schema_table; /* Information_schema table */ st_select_lex *schema_select_lex; diff --git a/storage/federatedx/federatedx_pushdown.cc b/storage/federatedx/federatedx_pushdown.cc index bfe421c8ab2..c53b35976f7 100644 --- a/storage/federatedx/federatedx_pushdown.cc +++ b/storage/federatedx/federatedx_pushdown.cc @@ -38,14 +38,14 @@ create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived) return 0; } } - + handler= new ha_federatedx_derived_handler(thd, derived); return handler; } -/* +/* Implementation class of the derived_handler interface for FEDERATEDX: class implementation */ @@ -62,7 +62,6 @@ ha_federatedx_derived_handler::~ha_federatedx_derived_handler() {} int ha_federatedx_derived_handler::init_scan() { - char query_buff[4096]; THD *thd; int rc= 0; @@ -76,12 +75,8 @@ int ha_federatedx_derived_handler::init_scan() txn= h->get_txn(thd); if ((rc= txn->acquire(share, thd, TRUE, iop))) DBUG_RETURN(rc); - - String derived_query(query_buff, sizeof(query_buff), thd->charset()); - derived_query.length(0); - derived->derived->print(&derived_query, QT_ORDINARY); - - if ((*iop)->query(derived_query.ptr(), derived_query.length())) + + if ((*iop)->query(derived->derived_spec.str, derived->derived_spec.length)) goto err; stored_result= (*iop)->store_result(); @@ -93,7 +88,7 @@ int ha_federatedx_derived_handler::init_scan() err: DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM); } - + int ha_federatedx_derived_handler::next_row() { int rc; @@ -167,7 +162,7 @@ create_federatedx_select_handler(THD* thd, SELECT_LEX *sel) return handler; } -/* +/* Implementation class of the select_handler interface for FEDERATEDX: class implementation */ @@ -175,7 +170,7 @@ create_federatedx_select_handler(THD* thd, SELECT_LEX *sel) ha_federatedx_select_handler::ha_federatedx_select_handler(THD *thd, SELECT_LEX *sel) : select_handler(thd, federatedx_hton), - share(NULL), txn(NULL), iop(NULL), stored_result(NULL) + share(NULL), txn(NULL), iop(NULL), stored_result(NULL) { select= sel; } diff --git a/storage/federatedx/federatedx_pushdown.h b/storage/federatedx/federatedx_pushdown.h index 961571b972c..673abcfc68d 100644 --- a/storage/federatedx/federatedx_pushdown.h +++ b/storage/federatedx/federatedx_pushdown.h @@ -17,7 +17,7 @@ #include "derived_handler.h" #include "select_handler.h" -/* +/* Implementation class of the derived_handler interface for FEDERATEDX: class declaration */ @@ -40,7 +40,7 @@ public: }; -/* +/* Implementation class of the select_handler interface for FEDERATEDX: class declaration */ From f0513de525863d9d1f6eac11fe98a737303ce2a6 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Mon, 11 Feb 2019 10:10:55 +0200 Subject: [PATCH 55/91] Fixed use of uninitialized value in wsrep_TOI_end() The if/else was a remnant from error voting code which was not included in the release. --- sql/wsrep_mysqld.cc | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 7a9c8922296..401b40590df 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -1884,7 +1884,6 @@ static int wsrep_TOI_begin(THD *thd, const char *db, const char *table, } static void wsrep_TOI_end(THD *thd) { - int ret; wsrep_to_isolation--; wsrep::client_state& client_state(thd->wsrep_cs()); DBUG_ASSERT(wsrep_thd_is_local_toi(thd)); @@ -1894,18 +1893,8 @@ static void wsrep_TOI_end(THD *thd) { if (wsrep_thd_is_local_toi(thd)) { wsrep_set_SE_checkpoint(client_state.toi_meta().gtid()); - if (thd->is_error() && !wsrep_must_ignore_error(thd)) - { - wsrep_apply_error err; - err.store(thd); - client_state.leave_toi(); - } - else - { - ret= client_state.leave_toi(); - } - - if (ret == 0) + int ret= client_state.leave_toi(); + if (!ret) { WSREP_DEBUG("TO END: %lld", client_state.toi_meta().seqno().get()); } From 4e7ee166a9c76eb3546356aabfd2dbc759671cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 11 Feb 2019 14:40:28 +0200 Subject: [PATCH 56/91] MDEV-18295 IMPORT TABLESPACE fails with instant-altered tables When importing a tablespace, we must initialize dummy DEFAULT NULL values for any instantly added columns in order to avoid a debug assertion failure when PageConverter::update_records() invokes rec_get_offsets(). Finally, when the operation completes, we must evict and reload the table definition, so that the correct default values for instantly added columns will be loaded. ha_innobase::discard_or_import_tablespace(): On successful IMPORT TABLESPACE, evict and reload the table definition, so that btr_cur_instant_init() will load the correct metadata. PageConverter::update_index_page(): Fill in dummy DEFAULT NULL values for instantly added columns. These will be replaced upon the completion of the operation by evicting and reloading the metadata. row_discard_tablespace(): Invoke dict_table_t::remove_instant(). After DISCARD TABLESPACE, the table is no longer in "instant ALTER" format, because there is no data file attached. --- .../innodb/r/instant_alter_import.result | 46 ++++++++++++++ .../suite/innodb/t/instant_alter_import.test | 52 ++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 61 +++++++++++++------ storage/innobase/row/row0import.cc | 23 ++++--- storage/innobase/row/row0mysql.cc | 9 +-- 5 files changed, 160 insertions(+), 31 deletions(-) create mode 100644 mysql-test/suite/innodb/r/instant_alter_import.result create mode 100644 mysql-test/suite/innodb/t/instant_alter_import.test diff --git a/mysql-test/suite/innodb/r/instant_alter_import.result b/mysql-test/suite/innodb/r/instant_alter_import.result new file mode 100644 index 00000000000..ab14d44bdff --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_import.result @@ -0,0 +1,46 @@ +set default_storage_engine=innodb; +# +# MDEV-18295 IMPORT TABLESPACE fails with instant-altered tables +# +create table t2 (x int, z int default 41); +alter table t2 discard tablespace; +create table t1 (x int); +insert into t1 values (1); +alter table t1 add z int default 42, algorithm instant; +select * from t1; +x z +1 42 +flush tables t1 for export; +unlock tables; +# The metadata has to be updated to instant ADD COLUMN. +alter table t2 import tablespace; +select * from t2; +x z +1 42 +insert into t2 set x=2; +select * from t2; +x z +1 42 +2 41 +alter table t1 discard tablespace; +flush tables t2 for export; +unlock tables; +# Both the metadata and the data file used instant ADD COLUMN. +alter table t1 import tablespace; +select * from t1; +x z +1 42 +2 41 +drop table t2; +create table t2 select * from t1; +alter table t1 discard tablespace; +flush tables t2 for export; +unlock tables; +# The instant ADD COLUMN has to be removed from the metadata. +alter table t1 import tablespace; +select * from t1; +x z +1 42 +2 41 +drop table t2; +drop table t1; diff --git a/mysql-test/suite/innodb/t/instant_alter_import.test b/mysql-test/suite/innodb/t/instant_alter_import.test new file mode 100644 index 00000000000..5bd10a7994e --- /dev/null +++ b/mysql-test/suite/innodb/t/instant_alter_import.test @@ -0,0 +1,52 @@ +--source include/have_innodb.inc +set default_storage_engine=innodb; + +--echo # +--echo # MDEV-18295 IMPORT TABLESPACE fails with instant-altered tables +--echo # + +create table t2 (x int, z int default 41); +alter table t2 discard tablespace; + +create table t1 (x int); +insert into t1 values (1); +alter table t1 add z int default 42, algorithm instant; +select * from t1; +flush tables t1 for export; +--let $MYSQLD_DATADIR= `select @@datadir` +--move_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg +--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd +unlock tables; + +--echo # The metadata has to be updated to instant ADD COLUMN. +alter table t2 import tablespace; + +select * from t2; +insert into t2 set x=2; +select * from t2; + +alter table t1 discard tablespace; +flush tables t2 for export; +--move_file $MYSQLD_DATADIR/test/t2.cfg $MYSQLD_DATADIR/test/t1.cfg +--copy_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t1.ibd +unlock tables; + +--echo # Both the metadata and the data file used instant ADD COLUMN. +alter table t1 import tablespace; +select * from t1; + +drop table t2; +create table t2 select * from t1; + +alter table t1 discard tablespace; +flush tables t2 for export; +--move_file $MYSQLD_DATADIR/test/t2.cfg $MYSQLD_DATADIR/test/t1.cfg +--copy_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t1.ibd +unlock tables; + +--echo # The instant ADD COLUMN has to be removed from the metadata. +alter table t1 import tablespace; +select * from t1; + +drop table t2; +drop table t1; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 509be41e48f..e8ad2357c0a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -12682,10 +12682,7 @@ ha_innobase::discard_or_import_tablespace( DBUG_RETURN(HA_ERR_TABLE_READONLY); } - dict_table_t* dict_table = m_prebuilt->table; - - if (dict_table->is_temporary()) { - + if (m_prebuilt->table->is_temporary()) { ib_senderrf( m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_CANNOT_DISCARD_TEMPORARY_TABLE); @@ -12693,11 +12690,11 @@ ha_innobase::discard_or_import_tablespace( DBUG_RETURN(HA_ERR_TABLE_NEEDS_UPGRADE); } - if (dict_table->space == fil_system.sys_space) { + if (m_prebuilt->table->space == fil_system.sys_space) { ib_senderrf( m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, ER_TABLE_IN_SYSTEM_TABLESPACE, - dict_table->name.m_name); + m_prebuilt->table->name.m_name); DBUG_RETURN(HA_ERR_TABLE_NEEDS_UPGRADE); } @@ -12706,7 +12703,7 @@ ha_innobase::discard_or_import_tablespace( /* Obtain an exclusive lock on the table. */ dberr_t err = row_mysql_lock_table( - m_prebuilt->trx, dict_table, LOCK_X, + m_prebuilt->trx, m_prebuilt->table, LOCK_X, discard ? "setting table lock for DISCARD TABLESPACE" : "setting table lock for IMPORT TABLESPACE"); @@ -12719,32 +12716,32 @@ ha_innobase::discard_or_import_tablespace( user may want to set the DISCARD flag in order to IMPORT a new tablespace. */ - if (!dict_table->is_readable()) { + if (!m_prebuilt->table->is_readable()) { ib_senderrf( m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_WARN, ER_TABLESPACE_MISSING, - dict_table->name.m_name); + m_prebuilt->table->name.m_name); } err = row_discard_tablespace_for_mysql( - dict_table->name.m_name, m_prebuilt->trx); + m_prebuilt->table->name.m_name, m_prebuilt->trx); - } else if (dict_table->is_readable()) { + } else if (m_prebuilt->table->is_readable()) { /* Commit the transaction in order to release the table lock. */ trx_commit_for_mysql(m_prebuilt->trx); ib::error() << "Unable to import tablespace " - << dict_table->name << " because it already" + << m_prebuilt->table->name << " because it already" " exists. Please DISCARD the tablespace" " before IMPORT."; ib_senderrf( m_prebuilt->trx->mysql_thd, IB_LOG_LEVEL_ERROR, - ER_TABLESPACE_EXISTS, dict_table->name.m_name); + ER_TABLESPACE_EXISTS, m_prebuilt->table->name.m_name); DBUG_RETURN(HA_ERR_TABLE_EXIST); } else { - err = row_import_for_mysql(dict_table, m_prebuilt); + err = row_import_for_mysql(m_prebuilt->table, m_prebuilt); if (err == DB_SUCCESS) { @@ -12760,12 +12757,35 @@ ha_innobase::discard_or_import_tablespace( /* Commit the transaction in order to release the table lock. */ trx_commit_for_mysql(m_prebuilt->trx); - if (err == DB_SUCCESS && !discard - && dict_stats_is_persistent_enabled(dict_table)) { + if (discard || err != DB_SUCCESS) { + DBUG_RETURN(convert_error_code_to_mysql( + err, m_prebuilt->table->flags, NULL)); + } + + /* Evict and reload the table definition in order to invoke + btr_cur_instant_init(). */ + table_id_t id = m_prebuilt->table->id; + ut_ad(id); + mutex_enter(&dict_sys->mutex); + dict_table_close(m_prebuilt->table, TRUE, FALSE); + dict_table_remove_from_cache(m_prebuilt->table); + m_prebuilt->table = dict_table_open_on_id(id, TRUE, + DICT_TABLE_OP_NORMAL); + mutex_exit(&dict_sys->mutex); + if (!m_prebuilt->table) { + err = DB_TABLE_NOT_FOUND; + } else { + if (const Field* ai = table->found_next_number_field) { + initialize_auto_increment(m_prebuilt->table, ai); + } + dict_stats_init(m_prebuilt->table); + } + + if (dict_stats_is_persistent_enabled(m_prebuilt->table)) { dberr_t ret; /* Adjust the persistent statistics. */ - ret = dict_stats_update(dict_table, + ret = dict_stats_update(m_prebuilt->table, DICT_STATS_RECALC_PERSISTENT); if (ret != DB_SUCCESS) { @@ -12775,11 +12795,12 @@ ha_innobase::discard_or_import_tablespace( ER_ALTER_INFO, "Error updating stats for table '%s'" " after table rebuild: %s", - dict_table->name.m_name, ut_strerr(ret)); + m_prebuilt->table->name.m_name, + ut_strerr(ret)); } } - DBUG_RETURN(convert_error_code_to_mysql(err, dict_table->flags, NULL)); + DBUG_RETURN(0); } /** diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 5a4321e5fe7..9cdb4cab764 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1820,13 +1820,22 @@ PageConverter::update_index_page( if (dict_index_is_clust(m_index->m_srv_index)) { if (page_is_root(page)) { + dict_index_t* index = const_cast( + m_index->m_srv_index); /* Preserve the PAGE_ROOT_AUTO_INC. */ - if (m_index->m_srv_index->table->supports_instant() - && btr_cur_instant_root_init( - const_cast( - m_index->m_srv_index), - page)) { - return(DB_CORRUPTION); + if (index->table->supports_instant()) { + if (btr_cur_instant_root_init(index, page)) { + return(DB_CORRUPTION); + } + + /* Provisionally set all instantly + added columns to be DEFAULT NULL. */ + for (unsigned i = index->n_core_fields; + i < index->n_fields; i++) { + dict_col_t* col = index->fields[i].col; + col->def_val.len = UNIV_SQL_NULL; + col->def_val.data = NULL; + } } } else { /* Clear PAGE_MAX_TRX_ID so that it can be diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 80a3d2f046b..007b4eee1a4 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3074,13 +3074,14 @@ row_discard_tablespace( table->flags2 |= DICT_TF2_DISCARDED; dict_table_change_id_in_cache(table, new_id); - /* Reset the root page numbers. */ + dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); + if (index) index->remove_instant(); - for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes); - index != 0; - index = UT_LIST_GET_NEXT(indexes, index)) { + /* Reset the root page numbers. */ + for (; index; index = UT_LIST_GET_NEXT(indexes, index)) { index->page = FIL_NULL; } + /* If the tablespace did not already exist or we couldn't write to it, we treat that as a successful DISCARD. It is unusable anyway. */ From 3a269a8b5272c15751f565daa1566d1f61a1f04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 11 Feb 2019 14:59:59 +0200 Subject: [PATCH 57/91] Record galera_var_load_data_splitting result after deprecating warning. --- .../suite/galera/r/galera_var_load_data_splitting.result | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result index 7c5fd44356e..9078e9ea985 100644 --- a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result +++ b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result @@ -3,6 +3,8 @@ connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; connection node_2; SET GLOBAL wsrep_load_data_splitting = TRUE; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release connection node_2; SELECT COUNT(*) = 95000 FROM t1; COUNT(*) = 95000 @@ -11,4 +13,6 @@ wsrep_last_committed_diff 1 connection node_1; SET GLOBAL wsrep_load_data_splitting = 1;; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release DROP TABLE t1; From b2dd88f095812e5d378e8caf3d397d0e8c27d1d2 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Tue, 12 Feb 2019 15:59:05 +1100 Subject: [PATCH 58/91] cmake/wsrep: allow disabling -DWITH_WSREP=OFF --- cmake/wsrep.cmake | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 44e00649993..37ed0c78cf5 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -28,20 +28,20 @@ OPTION(WITH_WSREP_ALL "Build all components of WSREP (unit tests, sample programs)" OFF) -# Set the patch version -SET(WSREP_PATCH_VERSION "22") - -# Obtain wsrep API version -FILE(STRINGS "${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26/wsrep_api.h" WSREP_API_VERSION - LIMIT_COUNT 1 REGEX "WSREP_INTERFACE_VERSION") -STRING(REGEX MATCH "([0-9]+)" WSREP_API_VERSION "${WSREP_API_VERSION}") - -SET(WSREP_VERSION "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}" - CACHE INTERNAL "WSREP version") - -SET(WSREP_PROC_INFO ${WITH_WSREP}) - IF(WITH_WSREP) + # Set the patch version + SET(WSREP_PATCH_VERSION "22") + + # Obtain wsrep API version + FILE(STRINGS "${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26/wsrep_api.h" WSREP_API_VERSION + LIMIT_COUNT 1 REGEX "WSREP_INTERFACE_VERSION") + STRING(REGEX MATCH "([0-9]+)" WSREP_API_VERSION "${WSREP_API_VERSION}") + + SET(WSREP_VERSION "${WSREP_API_VERSION}.${WSREP_PATCH_VERSION}" + CACHE INTERNAL "WSREP version") + + SET(WSREP_PROC_INFO ${WITH_WSREP}) + SET(WSREP_PATCH_VERSION "wsrep_${WSREP_VERSION}") if (NOT WITH_WSREP_ALL) SET(WSREP_LIB_WITH_UNIT_TESTS OFF CACHE BOOL From ce6505f890956f81354269a991e69f20babae8e4 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Tue, 12 Feb 2019 11:59:17 +0400 Subject: [PATCH 59/91] MDEV-18447 Assertion `!is_zero_datetime()' failed in Timestamp_or_zero_datetime::tv --- mysql-test/main/type_timestamp.result | 9 +++++++++ mysql-test/main/type_timestamp.test | 8 ++++++++ sql/sql_type.h | 8 +++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/type_timestamp.result b/mysql-test/main/type_timestamp.result index c2af8952f4f..a8e2cbb36c6 100644 --- a/mysql-test/main/type_timestamp.result +++ b/mysql-test/main/type_timestamp.result @@ -1164,5 +1164,14 @@ NULL NULL DROP TABLE t1, t2, t3; # +# MDEV-18447 Assertion `!is_zero_datetime()' failed in Timestamp_or_zero_datetime::tv +# +CREATE TABLE t1 (a TIMESTAMP DEFAULT 0, b TIMESTAMP DEFAULT 0, c TIME DEFAULT 0); +INSERT INTO t1 VALUES (0,0,0); +SELECT c IN (GREATEST(a,b)) FROM t1; +c IN (GREATEST(a,b)) +0 +DROP TABLE t1; +# # End of 10.4 tests # diff --git a/mysql-test/main/type_timestamp.test b/mysql-test/main/type_timestamp.test index 8b64fe0bfc3..08ca173ca02 100644 --- a/mysql-test/main/type_timestamp.test +++ b/mysql-test/main/type_timestamp.test @@ -760,6 +760,14 @@ CREATE TABLE t3 (pk INT PRIMARY KEY, b TIMESTAMP) ENGINE=MyISAM; SELECT ( SELECT b FROM t1 LIMIT 1 ) AS sq FROM t2 LEFT JOIN t3 USING (pk); DROP TABLE t1, t2, t3; +--echo # +--echo # MDEV-18447 Assertion `!is_zero_datetime()' failed in Timestamp_or_zero_datetime::tv +--echo # + +CREATE TABLE t1 (a TIMESTAMP DEFAULT 0, b TIMESTAMP DEFAULT 0, c TIME DEFAULT 0); +INSERT INTO t1 VALUES (0,0,0); +SELECT c IN (GREATEST(a,b)) FROM t1; +DROP TABLE t1; --echo # --echo # End of 10.4 tests diff --git a/sql/sql_type.h b/sql/sql_type.h index 5f53c5f4aae..3eb7d39742c 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -2435,6 +2435,12 @@ public: length(0); // safety } int save_in_field(Field *field, uint decimals) const; + Datetime to_datetime(THD *thd) const + { + return is_zero_datetime() ? + Datetime() : + Datetime(thd, Timestamp_or_zero_datetime(*this).tv()); + } bool is_zero_datetime() const { return length() == 0; @@ -2459,7 +2465,7 @@ public: Datetime to_datetime(THD *thd) const { return is_null() ? Datetime() : - Datetime(thd, Timestamp_or_zero_datetime(*this).tv()); + Timestamp_or_zero_datetime_native::to_datetime(thd); } void to_TIME(THD *thd, MYSQL_TIME *to) { From f06a0b5338694755842a58798bb3a9a40da78bfd Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Mon, 11 Feb 2019 14:47:08 +0200 Subject: [PATCH 60/91] Implement wsrep_load_data_splitting with streaming replication If wsrep_load_data_splitting is configured, change streaming replication parameters internally to match the original behavior, i.e. replicate on every 10000 rows. After load data is over, restore original streaming replication settings. Removed redundant wsrep_tc_log_commit(). --- sql/sql_load.cc | 64 ++++++++++++++++++++++----------------------- sql/wsrep_mysqld.cc | 51 ------------------------------------ sql/wsrep_mysqld.h | 9 ------- wsrep-lib | 2 +- 4 files changed, 32 insertions(+), 94 deletions(-) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index c95ef72a308..da5356ffb4b 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -100,41 +100,39 @@ public: #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) +/** If requested by wsrep_load_data_splitting and streaming replication is + not enabled, replicate a streaming fragment every 10,000 rows.*/ +class Wsrep_load_data_split { - DBUG_ENTER("wsrep_load_data_split"); - - if (!wsrep_load_data_splitting || !WSREP(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()->next()) - DBUG_RETURN(false); - - if (handlerton* hton= thd->transaction.stmt.ha_list->next()->ht()) +public: + Wsrep_load_data_split(THD *thd) + : m_thd(thd) + , m_load_data_splitting(wsrep_load_data_splitting) + , m_fragment_unit(thd->wsrep_trx().streaming_context().fragment_unit()) + , m_fragment_size(thd->wsrep_trx().streaming_context().fragment_size()) { - if (!(hton->flags & HTON_WSREP_REPLICATION)) - DBUG_RETURN(false); - WSREP_DEBUG("intermediate transaction commit in LOAD DATA"); - wsrep_tc_log_commit(thd); - table->file->extra(HA_EXTRA_FAKE_START_STMT); + if (WSREP(m_thd) && m_load_data_splitting) + { + /* Override streaming settings with backward compatible values for + load data splitting */ + m_thd->wsrep_cs().streaming_params(wsrep::streaming_context::row, 10000); + } } - 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); \ + ~Wsrep_load_data_split() + { + if (WSREP(m_thd) && m_load_data_splitting) + { + /* Restore original settings */ + m_thd->wsrep_cs().streaming_params(m_fragment_unit, m_fragment_size); + } } -#else /* WITH_WSREP */ -#define WSREP_LOAD_DATA_SPLIT(thd,table,info) /* empty */ +private: + THD *m_thd; + my_bool m_load_data_splitting; + enum wsrep::streaming_context::fragment_unit m_fragment_unit; + size_t m_fragment_size; +}; #endif /* WITH_WSREP */ class READ_INFO: public Load_data_param @@ -354,6 +352,9 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list, bool transactional_table __attribute__((unused)); DBUG_ENTER("mysql_load"); +#ifdef WITH_WSREP + Wsrep_load_data_split wsrep_load_data_split(thd); +#endif /* WITH_WSREP */ /* Bug #34283 mysqlbinlog leaves tmpfile after termination if binlog contains @@ -1005,7 +1006,6 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, DBUG_RETURN(-1); } - WSREP_LOAD_DATA_SPLIT(thd, table, info); err= write_record(thd, table, &info); table->auto_increment_field_not_null= FALSE; if (err) @@ -1148,7 +1148,6 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, DBUG_RETURN(-1); } - WSREP_LOAD_DATA_SPLIT(thd, table, info); err= write_record(thd, table, &info); table->auto_increment_field_not_null= FALSE; if (err) @@ -1271,7 +1270,6 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, DBUG_RETURN(-1); } - WSREP_LOAD_DATA_SPLIT(thd, table, info); err= write_record(thd, table, &info); table->auto_increment_field_not_null= false; if (err) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 401b40590df..06e713ceda0 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2499,57 +2499,6 @@ int wsrep_ordered_commit_if_no_binlog(THD* thd, bool all) return 0; } -wsrep_status_t wsrep_tc_log_commit(THD* thd) -{ - int cookie; - my_xid xid= thd->transaction.xid_state.xid.get_my_xid(); - - DBUG_ASSERT(thd->lex->sql_command == SQLCOM_LOAD); - if (wsrep_before_commit(thd, true)) - { - WSREP_DEBUG("wsrep_tc_log_commit: wsrep_before_commit failed %llu", - thd->thread_id); - return WSREP_TRX_FAIL; - } - cookie= tc_log->log_and_order(thd, xid, 1, false, true); - if (wsrep_after_commit(thd, true)) - { - WSREP_DEBUG("wsrep_tc_log_commit: wsrep_after_commit failed %llu", - thd->thread_id); - return WSREP_TRX_FAIL; - } - if (!cookie) - { - WSREP_DEBUG("log_and_order has failed %llu %d", thd->thread_id, cookie); - return WSREP_TRX_FAIL; - } - if (tc_log->unlog(cookie, xid)) - { - WSREP_DEBUG("log_and_order has failed %llu %d", thd->thread_id, cookie); - return WSREP_TRX_FAIL; - } - - if (wsrep_after_statement(thd)) - { - return WSREP_TRX_FAIL; - } - /* Set wsrep transaction id if not set. */ - if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID) - { - if (thd->wsrep_next_trx_id() == WSREP_UNDEFINED_TRX_ID) - { - thd->set_wsrep_next_trx_id(thd->query_id); - } - DBUG_ASSERT(thd->wsrep_next_trx_id() != WSREP_UNDEFINED_TRX_ID); - } - if (wsrep_start_transaction(thd, thd->wsrep_next_trx_id())) - { - return WSREP_TRX_FAIL; - } - DBUG_ASSERT(thd->wsrep_trx_id() != WSREP_UNDEFINED_TRX_ID); - return WSREP_OK; -} - int wsrep_thd_retry_counter(const THD *thd) { return thd->wsrep_retry_counter; diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 957f1ef3ab1..3c430ccf487 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -444,15 +444,6 @@ bool wsrep_provider_is_SR_capable(); */ int wsrep_ordered_commit_if_no_binlog(THD*, bool); -/** - * Commit the current transaction with the - * MySQL "Transaction Coordinator Log" (see `class TC_LOG` in sql/log.h). - * Calling this function will generate and assign a new wsrep transaction id - * for `thd`. - * @return WSREP_OK on success or other WSREP_* error code on failure - */ -wsrep_status_t wsrep_tc_log_commit(THD* thd); - /** * Initialize WSREP server instance. * diff --git a/wsrep-lib b/wsrep-lib index e7d72ae7f6a..20b52ff1ddc 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit e7d72ae7f6a6995a21d743389426a963429a1fff +Subproject commit 20b52ff1ddc3b2f547b7081471f46dcfa5efabc7 From f20dfeecc6a47251039289c5ca21a22517331865 Mon Sep 17 00:00:00 2001 From: Teemu Ollakka Date: Mon, 11 Feb 2019 17:14:28 +0200 Subject: [PATCH 61/91] Recorded galera_sr_load_data_splitting, galera_sr_load_data --- .../suite/galera_sr/r/galera_sr_load_data.result | 2 +- .../galera_sr/r/galera_sr_load_data_splitting.result | 10 ++++++++++ mysql-test/suite/galera_sr/t/galera_sr_load_data.test | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/galera_sr/r/galera_sr_load_data.result b/mysql-test/suite/galera_sr/r/galera_sr_load_data.result index a474a7e3ae8..354f9ca718a 100644 --- a/mysql-test/suite/galera_sr/r/galera_sr_load_data.result +++ b/mysql-test/suite/galera_sr/r/galera_sr_load_data.result @@ -9,5 +9,5 @@ SELECT COUNT(*) = 20000 FROM t1; COUNT(*) = 20000 1 wsrep_last_committed_diff -0 +1 DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result b/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result index b25a8877005..61e4b56aa43 100644 --- a/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result +++ b/mysql-test/suite/galera_sr/r/galera_sr_load_data_splitting.result @@ -1,9 +1,19 @@ +connection node_2; +connection node_1; SET SESSION wsrep_trx_fragment_size = 512; SET GLOBAL wsrep_load_data_splitting = TRUE; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connection node_2; +connection node_1; +connection node_2; SELECT COUNT(*) = 95000 FROM t1; COUNT(*) = 95000 1 wsrep_last_committed_diff 1 +connection node_1; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release DROP TABLE t1; diff --git a/mysql-test/suite/galera_sr/t/galera_sr_load_data.test b/mysql-test/suite/galera_sr/t/galera_sr_load_data.test index b430ace5d69..70f0926ed1b 100644 --- a/mysql-test/suite/galera_sr/t/galera_sr_load_data.test +++ b/mysql-test/suite/galera_sr/t/galera_sr_load_data.test @@ -33,7 +33,7 @@ CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; SELECT COUNT(*) = 20000 FROM t1; # LOAD-ing 20K rows causes 3 commits to be registered --disable_query_log ---eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before = 3 AS wsrep_last_committed_diff; +--eval SELECT $wsrep_last_committed_after - $wsrep_last_committed_before = 3 AS wsrep_last_committed_diff --enable_query_log DROP TABLE t1; From f07b76fcfd68a0ae394764b181c1305b86e8f55d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 5 Feb 2019 16:02:25 +0100 Subject: [PATCH 62/91] cleanup: remove reduntant variable --- scripts/mysql_install_db.sh | 2 -- scripts/mysql_system_tables_data.sql | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 82a8e175753..8cb55e519e7 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -507,11 +507,9 @@ cat_sql() case "$auth_root_authentication_method" in normal) - echo "SET @skip_auth_root_nopasswd=NULL;" echo "SET @auth_root_socket=NULL;" ;; socket) - echo "SET @skip_auth_root_nopasswd=1;" echo "SET @auth_root_socket='$auth_root_socket_user';" ;; esac diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql index 60867fc2bc3..bf473db7527 100644 --- a/scripts/mysql_system_tables_data.sql +++ b/scripts/mysql_system_tables_data.sql @@ -42,7 +42,7 @@ IF @auth_root_socket is not null THEN IF not exists(select 1 from information_schema.plugins where plugin_name='unix_socket') THEN INSTALL SONAME 'auth_socket'; END IF; END IF; -INSERT INTO global_priv SELECT * FROM tmp_user_nopasswd WHERE @had_user_table=0 AND @skip_auth_root_nopasswd IS NULL; +INSERT INTO global_priv SELECT * FROM tmp_user_nopasswd WHERE @had_user_table=0 AND @auth_root_socket IS NULL; INSERT INTO global_priv SELECT * FROM tmp_user_socket WHERE @had_user_table=0 AND @auth_root_socket IS NOT NULL; DROP TABLE tmp_user_nopasswd, tmp_user_socket; From b9f3f06857ac6f9105dc65caae19782f09b47fb3 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 5 Feb 2019 16:07:07 +0100 Subject: [PATCH 63/91] MDEV-12484 Enable unix socket authentication by default Change the default authentication for root@localhost to IDENTIFIED VIA mysql_native_password USING 'invalid' OR unix_socket which provides secure passwordless login, while still allowing SET PASSWORD to work as expected. Also create a second all-privilege account for the user that owns datadir (and thus has full access to the data anyway). Compile unix_socket plugin statically into the server. --- .../build_configurations/mysql_release.cmake | 3 +++ mysql-test/main/failed_auth_unixsocket.result | 2 +- mysql-test/main/failed_auth_unixsocket.test | 2 +- mysql-test/main/mysql_upgrade-6984.result | 2 +- mysql-test/main/mysql_upgrade-6984.test | 2 +- .../i_s_applicable_roles_is_default.result | 2 +- .../i_s_applicable_roles_is_default.test | 2 +- scripts/mysql_install_db.sh | 27 +++++++++++-------- scripts/mysql_system_tables_data.sql | 7 +++-- 9 files changed, 30 insertions(+), 19 deletions(-) diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake index 105855a0bd1..4b399a131f5 100644 --- a/cmake/build_configurations/mysql_release.cmake +++ b/cmake/build_configurations/mysql_release.cmake @@ -98,17 +98,20 @@ ELSEIF(RPM) SET(CHECKMODULE /usr/bin/checkmodule CACHE STRING "") SET(SEMODULE_PACKAGE /usr/bin/semodule_package CACHE STRING "") SET(WITH_LIBARCHIVE ON CACHE STRING "") + SET(PLUGIN_AUTH_SOCKET YES) ELSEIF(DEB) SET(WITH_SSL system CACHE STRING "") SET(WITH_ZLIB system CACHE STRING "") SET(WITH_LIBWRAP ON) SET(HAVE_EMBEDDED_PRIVILEGE_CONTROL ON) SET(WITH_LIBARCHIVE ON CACHE STRING "") + SET(PLUGIN_AUTH_SOCKET YES) ELSE() SET(WITH_SSL bundled CACHE STRING "") SET(WITH_ZLIB bundled CACHE STRING "") SET(WITH_JEMALLOC static CACHE STRING "") SET(WITH_LIBARCHIVE STATIC CACHE STRING "") + SET(PLUGIN_AUTH_SOCKET STATIC) ENDIF() IF(NOT COMPILATION_COMMENT) diff --git a/mysql-test/main/failed_auth_unixsocket.result b/mysql-test/main/failed_auth_unixsocket.result index 690476cd753..eb02479431b 100644 --- a/mysql-test/main/failed_auth_unixsocket.result +++ b/mysql-test/main/failed_auth_unixsocket.result @@ -8,6 +8,6 @@ flush privileges; connect(localhost,USER,,test,MASTER_PORT,MASTER_SOCKET); ERROR 28000: Access denied for user 'USER'@'localhost' ERROR 28000: Access denied for user 'USER'@'localhost' -update mysql.global_priv set priv=json_remove(priv, '$.plugin'); +update mysql.global_priv set priv=json_compact(json_remove(priv, '$.plugin')); flush privileges; uninstall plugin unix_socket; diff --git a/mysql-test/main/failed_auth_unixsocket.test b/mysql-test/main/failed_auth_unixsocket.test index a7ae7d64a6b..01fb09e1c46 100644 --- a/mysql-test/main/failed_auth_unixsocket.test +++ b/mysql-test/main/failed_auth_unixsocket.test @@ -36,7 +36,7 @@ connect (fail,localhost,$USER); --error ER_ACCESS_DENIED_NO_PASSWORD_ERROR change_user $USER; -update mysql.global_priv set priv=json_remove(priv, '$.plugin'); +update mysql.global_priv set priv=json_compact(json_remove(priv, '$.plugin')); flush privileges; uninstall plugin unix_socket; diff --git a/mysql-test/main/mysql_upgrade-6984.result b/mysql-test/main/mysql_upgrade-6984.result index 87f3c1a5359..ad48004a2a3 100644 --- a/mysql-test/main/mysql_upgrade-6984.result +++ b/mysql-test/main/mysql_upgrade-6984.result @@ -63,6 +63,6 @@ test Phase 7/7: Running 'FLUSH PRIVILEGES' OK connect con1,localhost,root,foo,,,; -update mysql.global_priv set priv=json_remove(priv, '$.plugin', '$.authentication_string'); +update mysql.global_priv set priv=json_compact(json_remove(priv, '$.plugin', '$.authentication_string')); flush privileges; set global event_scheduler=OFF; diff --git a/mysql-test/main/mysql_upgrade-6984.test b/mysql-test/main/mysql_upgrade-6984.test index a036b7a08a0..ad2b95314b0 100644 --- a/mysql-test/main/mysql_upgrade-6984.test +++ b/mysql-test/main/mysql_upgrade-6984.test @@ -17,7 +17,7 @@ update mysql.global_priv set priv=json_set(priv, '$.plugin', 'mysql_native_passw connect(con1,localhost,root,foo,,,); -update mysql.global_priv set priv=json_remove(priv, '$.plugin', '$.authentication_string'); +update mysql.global_priv set priv=json_compact(json_remove(priv, '$.plugin', '$.authentication_string')); flush privileges; # Load event table set global event_scheduler=OFF; diff --git a/mysql-test/suite/roles/i_s_applicable_roles_is_default.result b/mysql-test/suite/roles/i_s_applicable_roles_is_default.result index 32498d11390..ee7d17f3a1f 100644 --- a/mysql-test/suite/roles/i_s_applicable_roles_is_default.result +++ b/mysql-test/suite/roles/i_s_applicable_roles_is_default.result @@ -78,4 +78,4 @@ drop role role3; drop role role2; drop role role1; drop user foo; -update mysql.global_priv set priv=json_remove(priv, '$.default_role'); +update mysql.global_priv set priv=json_compact(json_remove(priv, '$.default_role')); diff --git a/mysql-test/suite/roles/i_s_applicable_roles_is_default.test b/mysql-test/suite/roles/i_s_applicable_roles_is_default.test index b6f6f9ba879..0e6436924a9 100644 --- a/mysql-test/suite/roles/i_s_applicable_roles_is_default.test +++ b/mysql-test/suite/roles/i_s_applicable_roles_is_default.test @@ -59,4 +59,4 @@ drop role role3; drop role role2; drop role role1; drop user foo; -update mysql.global_priv set priv=json_remove(priv, '$.default_role'); +update mysql.global_priv set priv=json_compact(json_remove(priv, '$.default_role')); diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 8cb55e519e7..54b5bed4546 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -37,8 +37,8 @@ force=0 in_rpm=0 ip_only=0 cross_bootstrap=0 -auth_root_authentication_method=normal -auth_root_socket_user='root' +auth_root_authentication_method=socket +auth_root_socket_user="" skip_test_db=0 usage() @@ -46,17 +46,17 @@ usage() cat < Date: Thu, 7 Feb 2019 15:11:45 +0100 Subject: [PATCH 64/91] MDEV-12834 mysql_secure_installation should ask about unix_socket authentication recognize new unix_socket protected accounts, and don't scare the user into setting the password for them --- scripts/mysql_secure_installation.sh | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh index 1bd21513d4d..9b5298949f3 100644 --- a/scripts/mysql_secure_installation.sh +++ b/scripts/mysql_secure_installation.sh @@ -17,6 +17,7 @@ config=".my.cnf.$$" command=".mysql.$$" +output=".my.output.$$" trap "interrupt" 1 2 3 6 15 @@ -216,7 +217,7 @@ prepare() { do_query() { echo "$1" >$command #sed 's,^,> ,' < $command # Debugging - $mysql_command --defaults-file=$config $defaults_extra_file $no_defaults $args <$command + $mysql_command --defaults-file=$config $defaults_extra_file $no_defaults $args <$command >$output return $? } @@ -268,15 +269,18 @@ get_root_password() { echo stty echo if [ "x$password" = "x" ]; then - hadpass=0 + emptypass=1 else - hadpass=1 + emptypass=0 fi rootpass=$password make_config - do_query "" + do_query "show create user root@localhost" status=$? done + if grep -q unix_socket $output; then + emptypass=0 + fi echo "OK, successfully used password, moving on..." echo } @@ -386,7 +390,7 @@ interrupt() { cleanup() { echo "Cleaning up..." - rm -f $config $command + rm -f $config $command $output } # Remove the files before exiting. @@ -405,9 +409,8 @@ echo "NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB" echo " SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!" echo echo "In order to log into MariaDB to secure it, we'll need the current" -echo "password for the root user. If you've just installed MariaDB, and" -echo "you haven't set the root password yet, the password will be blank," -echo "so you should just press enter here." +echo "password for the root user. If you've just installed MariaDB, and" +echo "haven't set the root password yet, you should just press enter here." echo get_root_password @@ -422,10 +425,10 @@ echo "root user without the proper authorisation." echo while true ; do - if [ $hadpass -eq 0 ]; then + if [ $emptypass -eq 1 ]; then echo $echo_n "Set root password? [Y/n] $echo_c" else - echo "You already have a root password set, so you can safely answer 'n'." + echo "You already have your root account protected, so you can safely answer 'n'." echo echo $echo_n "Change the root password? [Y/n] $echo_c" fi From ffa4677c098dd482a92f36f7658103822c39b2fe Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 7 Feb 2019 15:22:50 +0100 Subject: [PATCH 65/91] MDEV-12834 mysql_secure_installation should ask about unix_socket authentication Optionally, restore the default root authentication, that is mysql_native_password USING 'invalid' OR unix_socket --- scripts/mysql_secure_installation.sh | 36 ++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/scripts/mysql_secure_installation.sh b/scripts/mysql_secure_installation.sh index 9b5298949f3..6441bbdabbd 100644 --- a/scripts/mysql_secure_installation.sh +++ b/scripts/mysql_secure_installation.sh @@ -420,8 +420,40 @@ get_root_password # Set the root password # -echo "Setting the root password ensures that nobody can log into the MariaDB" -echo "root user without the proper authorisation." +echo "Setting the root password or using the unix_socket ensures that nobody" +echo "can log into the MariaDB root user without the proper authorisation." +echo + +while true ; do + if [ $emptypass -eq 1 ]; then + echo $echo_n "Enable unix_socket authentication? [Y/n] $echo_c" + else + echo "You already have your root account protected, so you can safely answer 'n'." + echo + echo $echo_n "Switch to unix_socket authentication [Y/n] $echo_c" + fi + read reply + validate_reply $reply && break +done + +if [ "$reply" = "n" ]; then + echo " ... skipping." +else + emptypass=0 + do_query "UPDATE mysql.global_priv SET priv=json_set(priv, '$.plugin', 'mysql_native_password', '$.authentication_string', 'invalid', '$.auth_or', json_array(json_object(), json_object('plugin', 'unix_socket'))) WHERE User='root';" + if [ $? -eq 0 ]; then + echo "Enabled successfully!" + echo "Reloading privilege tables.." + reload_privilege_tables + if [ $? -eq 1 ]; then + clean_and_exit + fi + echo + else + echo "Failed!" + clean_and_exit + fi +fi echo while true ; do From 4d5f85a3ec59b4a417da39a229fbb58e79c32029 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Tue, 12 Feb 2019 23:07:51 +0400 Subject: [PATCH 66/91] Bootstrap cleanups Remove unused key_thread_bootstrap. No more global bootstrap_error: it is return value of bootstrap() instead. --- sql/mysqld.cc | 9 +++------ sql/mysqld.h | 3 +-- sql/sql_parse.cc | 5 +++-- sql/sql_parse.h | 2 +- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d4ca35b36cc..b43f0772602 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -647,8 +647,6 @@ Lt_creator lt_creator; Ge_creator ge_creator; Le_creator le_creator; -int bootstrap_error; - THD_list server_threads; Rpl_filter* cur_rpl_filter; Rpl_filter* global_rpl_filter; @@ -1105,7 +1103,7 @@ static PSI_cond_info all_server_conds[]= { &key_TABLE_SHARE_COND_rotation, "TABLE_SHARE::COND_rotation", 0} }; -PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, +PSI_thread_key key_thread_delayed_insert, key_thread_handle_manager, key_thread_main, key_thread_one_connection, key_thread_signal_hand, key_thread_slave_background, key_rpl_parallel_thread; @@ -1113,7 +1111,6 @@ PSI_thread_key key_thread_ack_receiver; static PSI_thread_info all_server_threads[]= { - { &key_thread_bootstrap, "bootstrap", PSI_FLAG_GLOBAL}, { &key_thread_delayed_insert, "delayed_insert", 0}, { &key_thread_handle_manager, "manager", PSI_FLAG_GLOBAL}, { &key_thread_main, "main", PSI_FLAG_GLOBAL}, @@ -5768,9 +5765,9 @@ int mysqld_main(int argc, char **argv) if (opt_bootstrap) { select_thread_in_use= 0; // Allow 'kill' to work - bootstrap(mysql_stdin); + int bootstrap_error= bootstrap(mysql_stdin); if (!abort_loop) - unireg_abort(bootstrap_error ? 1 : 0); + unireg_abort(bootstrap_error); else { sleep(2); // Wait for kill diff --git a/sql/mysqld.h b/sql/mysqld.h index 3d056fb95c7..e2e1b999beb 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -297,7 +297,6 @@ extern "C" MYSQL_PLUGIN_IMPORT char **orig_argv; extern pthread_attr_t connection_attrib; extern my_bool old_mode; extern LEX_STRING opt_init_connect, opt_init_slave; -extern int bootstrap_error; extern char err_shared_dir[]; extern ulong connection_errors_select; extern ulong connection_errors_accept; @@ -394,7 +393,7 @@ extern PSI_cond_key key_COND_rpl_thread, key_COND_rpl_thread_queue, extern PSI_cond_key key_COND_wait_gtid, key_COND_gtid_ignore_duplicates; extern PSI_cond_key key_TABLE_SHARE_COND_rotation; -extern PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, +extern PSI_thread_key key_thread_delayed_insert, key_thread_handle_manager, key_thread_kill_server, key_thread_main, key_thread_one_connection, key_thread_signal_hand, key_thread_slave_background, key_rpl_parallel_thread; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1335461506d..7b6029aaa12 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -979,8 +979,9 @@ static char *fgets_fn(char *buffer, size_t size, fgets_input_t input, int *error } -void bootstrap(MYSQL_FILE *file) +int bootstrap(MYSQL_FILE *file) { + int bootstrap_error= 0; DBUG_ENTER("handle_bootstrap"); THD *thd= new THD(next_thread_id()); @@ -1105,7 +1106,7 @@ void bootstrap(MYSQL_FILE *file) thd->lex->restore_set_statement_var(); } delete thd; - DBUG_VOID_RETURN; + DBUG_RETURN(bootstrap_error); } diff --git a/sql/sql_parse.h b/sql/sql_parse.h index f458c4279dd..7c8ba37f1de 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -99,7 +99,7 @@ void create_table_set_open_action_and_adjust_tables(LEX *lex); void mysql_init_multi_delete(LEX *lex); bool multi_delete_set_locks_and_link_aux_tables(LEX *lex); void create_table_set_open_action_and_adjust_tables(LEX *lex); -void bootstrap(MYSQL_FILE *file); +int bootstrap(MYSQL_FILE *file); int mysql_execute_command(THD *thd); bool do_command(THD *thd); bool dispatch_command(enum enum_server_command command, THD *thd, From 58b950737c547df42c82744029cbcad235e0efd9 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 12 Feb 2019 13:11:32 -0800 Subject: [PATCH 67/91] MDEV-17096 Pushdown of simple derived tables to storage engines Added plugin system variable federated_pushdown. --- .../suite/federated/federatedx_create_handlers.test | 4 ++++ storage/federatedx/federatedx_pushdown.cc | 6 ++++++ storage/federatedx/ha_federatedx.cc | 10 ++++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test index 21539b61c8a..558b8465abd 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.test +++ b/mysql-test/suite/federated/federatedx_create_handlers.test @@ -1,6 +1,8 @@ --source have_federatedx.inc --source include/federated.inc +set global federated_pushdown=1; + connection slave; DROP TABLE IF EXISTS federated.t1; @@ -152,3 +154,5 @@ DROP TABLE federated.t1, federated.t2; connection default; source include/federated_cleanup.inc; + +set global federated_pushdown=0; diff --git a/storage/federatedx/federatedx_pushdown.cc b/storage/federatedx/federatedx_pushdown.cc index c53b35976f7..906d87c29ce 100644 --- a/storage/federatedx/federatedx_pushdown.cc +++ b/storage/federatedx/federatedx_pushdown.cc @@ -19,6 +19,9 @@ static derived_handler* create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived) { + if (!use_pushdown) + return 0; + ha_federatedx_derived_handler* handler = NULL; handlerton *ht= 0; @@ -144,6 +147,9 @@ void ha_federatedx_derived_handler::print_error(int, unsigned long) static select_handler* create_federatedx_select_handler(THD* thd, SELECT_LEX *sel) { + if (!use_pushdown) + return 0; + ha_federatedx_select_handler* handler = NULL; handlerton *ht= 0; diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 918fbef711a..f55b0bc779d 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -3677,11 +3677,17 @@ err1: return error; } -#include "federatedx_pushdown.cc" struct st_mysql_storage_engine federatedx_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; +my_bool use_pushdown; +static MYSQL_SYSVAR_BOOL(pushdown, use_pushdown, 0, + "Use query fragments pushdown capabilities", NULL, NULL, FALSE); +static struct st_mysql_sys_var* sysvars[]= { MYSQL_SYSVAR(pushdown) }; + +#include "federatedx_pushdown.cc" + maria_declare_plugin(federatedx) { MYSQL_STORAGE_ENGINE_PLUGIN, @@ -3694,7 +3700,7 @@ maria_declare_plugin(federatedx) federatedx_done, /* Plugin Deinit */ 0x0201 /* 2.1 */, NULL, /* status variables */ - NULL, /* system variables */ + sysvars, /* system variables */ "2.1", /* string version */ MariaDB_PLUGIN_MATURITY_STABLE /* maturity */ } From 17d00d9a94da2c2b57fc7cf75036d92ee6dc9298 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 12 Feb 2019 14:00:48 -0800 Subject: [PATCH 68/91] MDEV-17096 Pushdown of simple derived tables to storage engines Made the setting of the system variable federated_pushdown at the default connection. --- mysql-test/suite/federated/federatedx_create_handlers.result | 3 +++ mysql-test/suite/federated/federatedx_create_handlers.test | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/federated/federatedx_create_handlers.result b/mysql-test/suite/federated/federatedx_create_handlers.result index a25b0191e55..473972c2cd4 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.result +++ b/mysql-test/suite/federated/federatedx_create_handlers.result @@ -4,6 +4,8 @@ connection master; CREATE DATABASE federated; connection slave; CREATE DATABASE federated; +connection default; +set global federated_pushdown=1; connection slave; DROP TABLE IF EXISTS federated.t1; Warnings: @@ -301,6 +303,7 @@ DROP TABLE federated.t1, federated.t2, federated.t3; connection slave; DROP TABLE federated.t1, federated.t2; connection default; +set global federated_pushdown=0; connection master; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/federatedx_create_handlers.test b/mysql-test/suite/federated/federatedx_create_handlers.test index 558b8465abd..373b2aaaa33 100644 --- a/mysql-test/suite/federated/federatedx_create_handlers.test +++ b/mysql-test/suite/federated/federatedx_create_handlers.test @@ -1,6 +1,8 @@ --source have_federatedx.inc --source include/federated.inc +connection default; + set global federated_pushdown=1; connection slave; @@ -153,6 +155,7 @@ DROP TABLE federated.t1, federated.t2; connection default; +set global federated_pushdown=0; + source include/federated_cleanup.inc; -set global federated_pushdown=0; From 4f5c65367afaa1a633a0fee8754f24a944c681b5 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 13 Feb 2019 11:31:55 +1100 Subject: [PATCH 69/91] cmake-wsrep: friendly error message about missing wsrep_api.h Without this commit the error message is: $ cmake . -DWITH_WSREP=ON -- Running cmake version 3.12.1 -- MariaDB 10.4.3 CMake Error at cmake/wsrep.cmake:36 (FILE): FILE STRINGS file ".../mariadb-server-10.4/wsrep-lib/wsrep-API/v26/wsrep_api.h" cannot be read. Call Stack (most recent call first): CMakeLists.txt:147 (INCLUDE) Having 'git config cmake.update-submodules yes' nicely updates the build without error. $ cmake . -DWITH_WSREP=ON -- Running cmake version 3.12.1 -- MariaDB 10.4.3 Submodule path 'wsrep-lib': checked out 'e7d72ae7f6a6995a21d743389426a963429a1fff' Submodule path 'wsrep-lib/wsrep-API/v26': checked out '75a5f452f2ba07b0f4a3a9a94825fccc71b27398' --- cmake/submodules.cmake | 2 +- cmake/wsrep.cmake | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cmake/submodules.cmake b/cmake/submodules.cmake index c2a415c6063..9f04c26e8d6 100644 --- a/cmake/submodules.cmake +++ b/cmake/submodules.cmake @@ -31,7 +31,7 @@ ENDIF() IF(update_result OR NOT EXISTS ${CMAKE_SOURCE_DIR}/libmariadb/CMakeLists.txt) MESSAGE(FATAL_ERROR "No MariaDB Connector/C! Run - git submodule update --init + git submodule update --init --recursive Then restart the build. ") ENDIF() diff --git a/cmake/wsrep.cmake b/cmake/wsrep.cmake index 37ed0c78cf5..603f1955e5f 100644 --- a/cmake/wsrep.cmake +++ b/cmake/wsrep.cmake @@ -32,6 +32,12 @@ IF(WITH_WSREP) # Set the patch version SET(WSREP_PATCH_VERSION "22") + IF(NOT EXISTS "${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26/wsrep_api.h") + MESSAGE(FATAL_ERROR "No MariaDB wsrep-API code! Run + ${GIT_EXECUTABLE} submodule update --init --recursive +Then restart the build. +") + ENDIF() # Obtain wsrep API version FILE(STRINGS "${CMAKE_SOURCE_DIR}/wsrep-lib/wsrep-API/v26/wsrep_api.h" WSREP_API_VERSION LIMIT_COUNT 1 REGEX "WSREP_INTERFACE_VERSION") From 6b979416e0e4eac0a036ca5f2b81b748a3d2e680 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Thu, 10 Jan 2019 05:55:23 +0530 Subject: [PATCH 70/91] Extending the API for json_writer by introdcing classes for Json_writer_object and Json_writer_array. These classes will be used for the implementation of the optimizer trace. --- sql/my_json_writer.cc | 73 +++++++++-- sql/my_json_writer.h | 285 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 348 insertions(+), 10 deletions(-) diff --git a/sql/my_json_writer.cc b/sql/my_json_writer.cc index d219e88b98b..9c4d63f9c4a 100644 --- a/sql/my_json_writer.cc +++ b/sql/my_json_writer.cc @@ -16,7 +16,6 @@ #include "mariadb.h" #include "sql_priv.h" #include "sql_string.h" - #include "my_json_writer.h" void Json_writer::append_indent() @@ -62,6 +61,7 @@ void Json_writer::end_object() indent_level-=INDENT_SIZE; if (!first_child) append_indent(); + first_child= false; output.append("}"); } @@ -129,7 +129,6 @@ void Json_writer::add_ll(longlong val) add_unquoted_str(buf); } - /* Add a memory size, printing in Kb, Kb, Gb if necessary */ void Json_writer::add_size(longlong val) { @@ -173,7 +172,7 @@ void Json_writer::add_null() void Json_writer::add_unquoted_str(const char* str) { - if (fmt_helper.on_add_str(str)) + if (fmt_helper.on_add_str(str, 0)) return; if (!element_started) @@ -183,10 +182,9 @@ void Json_writer::add_unquoted_str(const char* str) element_started= false; } - void Json_writer::add_str(const char *str) { - if (fmt_helper.on_add_str(str)) + if (fmt_helper.on_add_str(str, 0)) return; if (!element_started) @@ -198,12 +196,70 @@ void Json_writer::add_str(const char *str) element_started= false; } +/* + This function is used to add only num_bytes of str to the output string +*/ + +void Json_writer::add_str(const char* str, size_t num_bytes) +{ + if (fmt_helper.on_add_str(str, num_bytes)) + return; + + if (!element_started) + start_element(); + + output.append('"'); + output.append(str, num_bytes); + output.append('"'); + element_started= false; +} void Json_writer::add_str(const String &str) { - add_str(str.ptr()); + add_str(str.ptr(), str.length()); } +Json_writer_object::Json_writer_object(Json_writer *writer):Json_writer_struct(writer) +{ + if (my_writer) + my_writer->start_object(); +} + +Json_writer_object::Json_writer_object(Json_writer *writer, const char *str) + :Json_writer_struct(writer) +{ + if (my_writer) + my_writer->add_member(str).start_object(); + +} +Json_writer_object::~Json_writer_object() +{ + if (!closed && my_writer) + my_writer->end_object(); + closed= TRUE; +} + +Json_writer_array::Json_writer_array(Json_writer *writer):Json_writer_struct(writer) +{ + if (my_writer) + my_writer->start_array(); +} + +Json_writer_array::Json_writer_array(Json_writer *writer, const char *str) + :Json_writer_struct(writer) +{ + if (my_writer) + my_writer->add_member(str).start_array(); + +} +Json_writer_array::~Json_writer_array() +{ + if (!closed && my_writer) + { + my_writer->end_array(); + closed= TRUE; + } +} bool Single_line_formatting_helper::on_add_member(const char *name) { @@ -267,11 +323,12 @@ void Single_line_formatting_helper::on_start_object() } -bool Single_line_formatting_helper::on_add_str(const char *str) +bool Single_line_formatting_helper::on_add_str(const char *str, + size_t num_bytes) { if (state == IN_ARRAY) { - size_t len= strlen(str); + size_t len= num_bytes ? num_bytes : strlen(str); // New length will be: // "$string", diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h index 3c127bd178c..fcf853b0b62 100644 --- a/sql/my_json_writer.h +++ b/sql/my_json_writer.h @@ -13,7 +13,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +#ifndef JSON_WRITER_INCLUDED +#define JSON_WRITER_INCLUDED +#include "my_base.h" +#include "sql_select.h" +class Opt_trace_stmt; +class Opt_trace_context; class Json_writer; +struct TABLE_LIST; + /* Single_line_formatting_helper is used by Json_writer to do better formatting @@ -85,7 +93,7 @@ public: void on_start_object(); // on_end_object() is not needed. - bool on_add_str(const char *str); + bool on_add_str(const char *str, size_t num_bytes); void flush_on_one_line(); void disable_and_flush(); @@ -105,7 +113,10 @@ public: /* Add atomic values */ void add_str(const char* val); + void add_str(const char* val, size_t num_bytes); void add_str(const String &str); + void add_str(Item *item); + void add_table_name(JOIN_TAB *tab); void add_ll(longlong val); void add_size(longlong val); @@ -151,6 +162,276 @@ public: String output; }; +/* A class to add values to Json_writer_object and Json_writer_array */ +class Json_value_context +{ + Json_writer* writer; + public: + void init(Json_writer *my_writer) { writer= my_writer; } + void add_str(const char* val) + { + if (writer) + writer->add_str(val); + } + void add_str(const char* val, size_t length) + { + if (writer) + writer->add_str(val); + } + void add_str(const String &str) + { + if (writer) + writer->add_str(str); + } + void add_str(LEX_CSTRING str) + { + if (writer) + writer->add_str(str.str); + } + void add_str(Item *item) + { + if (writer) + writer->add_str(item); + } + + void add_ll(longlong val) + { + if (writer) + writer->add_ll(val); + } + void add_size(longlong val) + { + if (writer) + writer->add_size(val); + } + void add_double(double val) + { + if (writer) + writer->add_double(val); + } + void add_bool(bool val) + { + if (writer) + writer->add_bool(val); + } + void add_null() + { + if (writer) + writer->add_null(); + } + void add_table_name(JOIN_TAB *tab) + { + if (writer) + writer->add_table_name(tab); + } +}; + +/* A common base for Json_writer_object and Json_writer_array */ +class Json_writer_struct +{ +protected: + Json_writer* my_writer; + Json_value_context context; + /* + Tells when a json_writer_struct has been closed or not + */ + bool closed; + +public: + Json_writer_struct(Json_writer* writer) + { + my_writer= writer; + context.init(writer); + closed= false; + } +}; + + +/* + RAII-based class to start/end writing a JSON object into the JSON document +*/ + +class Json_writer_object:public Json_writer_struct +{ +private: + void add_member(const char *name) + { + if (my_writer) + my_writer->add_member(name); + } +public: + Json_writer_object(Json_writer *w); + Json_writer_object(Json_writer *w, const char *str); + Json_writer_object& add(const char *name, bool value) + { + add_member(name); + context.add_bool(value); + return *this; + } + Json_writer_object& add(const char* name, uint value) + { + add_member(name); + context.add_ll(value); + return *this; + } + Json_writer_object& add(const char* name, ha_rows value) + { + add_member(name); + context.add_ll(value); + return *this; + } + Json_writer_object& add(const char *name, longlong value) + { + add_member(name); + context.add_ll(value); + return *this; + } + Json_writer_object& add(const char *name, double value) + { + add_member(name); + context.add_double(value); + return *this; + } + Json_writer_object& add(const char *name, size_t value) + { + add_member(name); + context.add_ll(value); + return *this; + } + Json_writer_object& add(const char *name, const char *value) + { + add_member(name); + context.add_str(value); + return *this; + } + Json_writer_object& add(const char *name, const char *value, size_t num_bytes) + { + add_member(name); + context.add_str(value, num_bytes); + return *this; + } + Json_writer_object& add(const char *name, const String &value) + { + add_member(name); + context.add_str(value); + return *this; + } + Json_writer_object& add(const char *name, LEX_CSTRING value) + { + add_member(name); + context.add_str(value.str); + return *this; + } + Json_writer_object& add(const char *name, Item *value) + { + add_member(name); + context.add_str(value); + return *this; + } + Json_writer_object& add_null(const char*name) + { + add_member(name); + context.add_null(); + return *this; + } + Json_writer_object& add_table_name(JOIN_TAB *tab) + { + add_member("table"); + context.add_table_name(tab); + return *this; + } + void end() + { + if (my_writer) + my_writer->end_object(); + closed= TRUE; + } + ~Json_writer_object(); +}; + + +/* + RAII-based class to start/end writing a JSON array into the JSON document +*/ +class Json_writer_array:public Json_writer_struct +{ +public: + Json_writer_array(Json_writer *w); + Json_writer_array(Json_writer *w, const char *str); + void end() + { + if (my_writer) + my_writer->end_array(); + closed= TRUE; + } + Json_writer_array& add(bool value) + { + context.add_bool(value); + return *this; + } + Json_writer_array& add(uint value) + { + context.add_ll(value); + return *this; + } + Json_writer_array& add(ha_rows value) + { + context.add_ll(value); + return *this; + } + Json_writer_array& add(longlong value) + { + context.add_ll(value); + return *this; + } + Json_writer_array& add(double value) + { + context.add_double(value); + return *this; + } + Json_writer_array& add(size_t value) + { + context.add_ll(value); + return *this; + } + Json_writer_array& add(const char *value) + { + context.add_str(value); + return *this; + } + Json_writer_array& add(const char *value, size_t num_bytes) + { + context.add_str(value, num_bytes); + return *this; + } + Json_writer_array& add(const String &value) + { + context.add_str(value); + return *this; + } + Json_writer_array& add(LEX_CSTRING value) + { + context.add_str(value.str); + return *this; + } + Json_writer_array& add(Item *value) + { + context.add_str(value); + return *this; + } + Json_writer_array& add_null() + { + context.add_null(); + return *this; + } + Json_writer_array& add_table_name(JOIN_TAB *tab) + { + context.add_table_name(tab); + return *this; + } + ~Json_writer_array(); +}; + /* RAII-based helper class to detect incorrect use of Json_writer. @@ -192,4 +473,4 @@ public: #endif }; - +#endif From be8709eb7bdf2a68a1c04fd8ab368113f5f39b63 Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Wed, 13 Feb 2019 11:22:16 +0530 Subject: [PATCH 71/91] MDEV-6111 Optimizer Trace This task involves the implementation for the optimizer trace. This feature produces a trace for any SELECT/UPDATE/DELETE/, which contains information about decisions taken by the optimizer during the optimization phase (choice of table access method, various costs, transformations, etc). This feature would help to tell why some decisions were taken by the optimizer and why some were rejected. Trace is session-local, controlled by the @@optimizer_trace variable. To enable optimizer trace we need to write: set @@optimizer_trace variable= 'enabled=on'; To display the trace one can run: SELECT trace FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE; This task also involves: MDEV-18489: Limit the memory used by the optimizer trace introduces a switch optimizer_trace_max_mem_size which limits the memory used by the optimizer trace. This was implemented by Sergei Petrunia. --- libmysqld/CMakeLists.txt | 1 + mysql-test/main/information_schema.result | 3 + .../information_schema_all_engines.result | 8 +- mysql-test/main/mysqld--help.result | 8 + mysql-test/main/opt_trace.result | 3499 +++++++++++++++++ mysql-test/main/opt_trace.test | 335 ++ mysql-test/main/opt_trace_index_merge.result | 249 ++ mysql-test/main/opt_trace_index_merge.test | 21 + .../main/opt_trace_index_merge_innodb.result | 242 ++ .../main/opt_trace_index_merge_innodb.test | 31 + mysql-test/main/opt_trace_security.result | 396 ++ mysql-test/main/opt_trace_security.test | 197 + .../suite/funcs_1/r/is_columns_is.result | 8 + .../funcs_1/r/is_columns_is_embedded.result | 8 + .../suite/funcs_1/r/is_tables_is.result | 50 + .../funcs_1/r/is_tables_is_embedded.result | 50 + .../r/sysvars_server_embedded,32bit.rdiff | 319 +- .../sys_vars/r/sysvars_server_embedded.result | 28 + .../r/sysvars_server_notembedded,32bit.rdiff | 339 +- .../r/sysvars_server_notembedded.result | 28 + sql/CMakeLists.txt | 1 + sql/handler.h | 1 + sql/my_json_writer.cc | 16 +- sql/my_json_writer.h | 228 +- sql/opt_range.cc | 845 +++- sql/opt_range.h | 2 +- sql/opt_subselect.cc | 66 +- sql/opt_table_elimination.cc | 30 +- sql/opt_trace.cc | 722 ++++ sql/opt_trace.h | 201 + sql/opt_trace_context.h | 92 + sql/set_var.h | 9 + sql/sp_head.cc | 13 + sql/sp_head.h | 1 + sql/sql_class.cc | 14 + sql/sql_class.h | 15 + sql/sql_derived.cc | 49 +- sql/sql_explain.cc | 2 +- sql/sql_parse.cc | 8 + sql/sql_prepare.cc | 12 + sql/sql_select.cc | 636 ++- sql/sql_show.cc | 7 + sql/sql_test.cc | 27 +- sql/sql_test.h | 2 + sql/sql_view.cc | 10 + sql/sys_vars.cc | 18 + sql/table.cc | 2 + 47 files changed, 8227 insertions(+), 622 deletions(-) create mode 100644 mysql-test/main/opt_trace.result create mode 100644 mysql-test/main/opt_trace.test create mode 100644 mysql-test/main/opt_trace_index_merge.result create mode 100644 mysql-test/main/opt_trace_index_merge.test create mode 100644 mysql-test/main/opt_trace_index_merge_innodb.result create mode 100644 mysql-test/main/opt_trace_index_merge_innodb.test create mode 100644 mysql-test/main/opt_trace_security.result create mode 100644 mysql-test/main/opt_trace_security.test create mode 100644 sql/opt_trace.cc create mode 100644 sql/opt_trace.h create mode 100644 sql/opt_trace_context.h diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index dfb5d4ce86f..26df0c60b15 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -122,6 +122,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ../sql/sql_tvc.cc ../sql/sql_tvc.h ../sql/opt_split.cc ../sql/item_vers.cc + ../sql/opt_trace.cc ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} ) diff --git a/mysql-test/main/information_schema.result b/mysql-test/main/information_schema.result index b76d9f64a9f..dd093aae5e9 100644 --- a/mysql-test/main/information_schema.result +++ b/mysql-test/main/information_schema.result @@ -67,6 +67,7 @@ GLOBAL_VARIABLES INDEX_STATISTICS KEY_CACHES KEY_COLUMN_USAGE +OPTIMIZER_TRACE PARAMETERS PARTITIONS PLUGINS @@ -864,6 +865,8 @@ information_schema COLUMNS COLUMN_DEFAULT information_schema COLUMNS COLUMN_TYPE information_schema COLUMNS GENERATION_EXPRESSION information_schema EVENTS EVENT_DEFINITION +information_schema OPTIMIZER_TRACE QUERY +information_schema OPTIMIZER_TRACE TRACE information_schema PARAMETERS DTD_IDENTIFIER information_schema PARTITIONS PARTITION_EXPRESSION information_schema PARTITIONS SUBPARTITION_EXPRESSION diff --git a/mysql-test/main/information_schema_all_engines.result b/mysql-test/main/information_schema_all_engines.result index 2916858b5a6..9ba4d20c76d 100644 --- a/mysql-test/main/information_schema_all_engines.result +++ b/mysql-test/main/information_schema_all_engines.result @@ -43,6 +43,7 @@ INNODB_TABLESPACES_SCRUBBING INNODB_TRX KEY_CACHES KEY_COLUMN_USAGE +OPTIMIZER_TRACE PARAMETERS PARTITIONS PLUGINS @@ -123,6 +124,7 @@ INNODB_TABLESPACES_SCRUBBING SPACE INNODB_TRX trx_id KEY_CACHES KEY_CACHE_NAME KEY_COLUMN_USAGE CONSTRAINT_SCHEMA +OPTIMIZER_TRACE QUERY PARAMETERS SPECIFIC_SCHEMA PARTITIONS TABLE_SCHEMA PLUGINS PLUGIN_NAME @@ -203,6 +205,7 @@ INNODB_TABLESPACES_SCRUBBING SPACE INNODB_TRX trx_id KEY_CACHES KEY_CACHE_NAME KEY_COLUMN_USAGE CONSTRAINT_SCHEMA +OPTIMIZER_TRACE QUERY PARAMETERS SPECIFIC_SCHEMA PARTITIONS TABLE_SCHEMA PLUGINS PLUGIN_NAME @@ -288,6 +291,7 @@ INNODB_TABLESPACES_SCRUBBING information_schema.INNODB_TABLESPACES_SCRUBBING 1 INNODB_TRX information_schema.INNODB_TRX 1 KEY_CACHES information_schema.KEY_CACHES 1 KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1 +OPTIMIZER_TRACE information_schema.OPTIMIZER_TRACE 1 PARAMETERS information_schema.PARAMETERS 1 PARTITIONS information_schema.PARTITIONS 1 PLUGINS information_schema.PLUGINS 1 @@ -358,6 +362,7 @@ Database: information_schema | INNODB_TRX | | KEY_CACHES | | KEY_COLUMN_USAGE | +| OPTIMIZER_TRACE | | PARAMETERS | | PARTITIONS | | PLUGINS | @@ -428,6 +433,7 @@ Database: INFORMATION_SCHEMA | INNODB_TRX | | KEY_CACHES | | KEY_COLUMN_USAGE | +| OPTIMIZER_TRACE | | PARAMETERS | | PARTITIONS | | PLUGINS | @@ -459,5 +465,5 @@ Wildcard: inf_rmation_schema | information_schema | SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') GROUP BY TABLE_SCHEMA; table_schema count(*) -information_schema 65 +information_schema 66 mysql 31 diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index d621c5c8cae..47ebfa7a8ab 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -693,6 +693,12 @@ The following specify which files/extra groups are read (specified before remain extended_keys, exists_to_in, orderby_uses_equalities, condition_pushdown_for_derived, split_materialized, condition_pushdown_for_subquery + --optimizer-trace=name + Controls tracing of the Optimizer: + optimizer_trace=option=val[,option=val...], where option + is one of {enabled} and val is one of {on, off, default} + --optimizer-trace-max-mem-size=# + Maximum allowed size of an optimizer trace --optimizer-use-condition-selectivity=# Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial @@ -1563,6 +1569,8 @@ optimizer-prune-level 1 optimizer-search-depth 62 optimizer-selectivity-sampling-limit 100 optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on +optimizer-trace +optimizer-trace-max-mem-size 1048576 optimizer-use-condition-selectivity 4 performance-schema FALSE performance-schema-accounts-size -1 diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result new file mode 100644 index 00000000000..22cde925b5e --- /dev/null +++ b/mysql-test/main/opt_trace.result @@ -0,0 +1,3499 @@ +SELECT table_name, column_name FROM information_schema.columns where table_name="OPTIMIZER_TRACE"; +table_name column_name +OPTIMIZER_TRACE QUERY +OPTIMIZER_TRACE TRACE +OPTIMIZER_TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE +OPTIMIZER_TRACE INSUFFICIENT_PRIVILEGES +show variables like 'optimizer_trace'; +Variable_name Value +optimizer_trace enabled=off +set optimizer_trace="enabled=on"; +show variables like 'optimizer_trace'; +Variable_name Value +optimizer_trace enabled=on +set optimizer_trace="enabled=off"; +create table t1 (a int, b int); +insert into t1 values (1,2),(2,3); +create table t2 (b int); +insert into t2 values (1),(2); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze table t2; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +create function f1 (a int) returns INT +return 1; +create view v1 as select * from t1 where t1.a=1; +create view v2 as select * from t1 where t1.a=1 group by t1.b; +set optimizer_trace="enabled=on"; +# Mergeable views/derived tables +select * from v1; +a b +1 2 +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +select * from v1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "view": { + "table": "v1", + "select_id": 2, + "merged": true + } + }, + { + "join_preparation": { + "select_id": 2, + "steps": [ + { + "expanded_query": "/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1" + } + ] + } + }, + { + "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `v1`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.a = 1", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "multiple equal(1, t1.a)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "multiple equal(1, t1.a)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "multiple equal(1, t1.a)" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [] + }, + { + "rows_estimation": [ + { + "selectivity_for_indexes": [], + "selectivity_for_columns": [ + { + "column_name": "a", + "selectivity_from_histograms": 0.5 + } + ] + }, + { + "table": "t1", + "table_scan": { + "rows": 2, + "cost": 2.0044 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 1, + "cost": 2.2044, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t1.a = 1", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": "t1.a = 1" + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +select * from (select * from t1 where t1.a=1)q; +a b +1 2 +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +select * from (select * from t1 where t1.a=1)q { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "derived": { + "table": "q", + "select_id": 2, + "merged": true + } + }, + { + "join_preparation": { + "select_id": 2, + "steps": [ + { + "expanded_query": "/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1" + } + ] + } + }, + { + "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from (/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1) `q`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.a = 1", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "multiple equal(1, t1.a)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "multiple equal(1, t1.a)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "multiple equal(1, t1.a)" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [] + }, + { + "rows_estimation": [ + { + "selectivity_for_indexes": [], + "selectivity_for_columns": [ + { + "column_name": "a", + "selectivity_from_histograms": 0.5 + } + ] + }, + { + "table": "t1", + "table_scan": { + "rows": 2, + "cost": 2.0044 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 1, + "cost": 2.2044, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t1.a = 1", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": "t1.a = 1" + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +# Non-Mergeable views +select * from v2; +a b +1 2 +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +select * from v2 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "view": { + "table": "v2", + "select_id": 2, + "materialized": true + } + }, + { + "join_preparation": { + "select_id": 2, + "steps": [ + { + "expanded_query": "/* select#2 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` = 1 group by `t1`.`b`" + } + ] + } + }, + { + "expanded_query": "/* select#1 */ select `v2`.`a` AS `a`,`v2`.`b` AS `b` from `v2`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "join_optimization": { + "select_id": 2, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.a = 1", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "multiple equal(1, t1.a)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "multiple equal(1, t1.a)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "multiple equal(1, t1.a)" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [] + }, + { + "rows_estimation": [ + { + "selectivity_for_indexes": [], + "selectivity_for_columns": [ + { + "column_name": "a", + "selectivity_from_histograms": 0.5 + } + ] + }, + { + "table": "t1", + "table_scan": { + "rows": 2, + "cost": 2.0044 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 1, + "cost": 2.2044, + "chosen": true, + "use_tmp_table": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t1.a = 1", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": "t1.a = 1" + } + ] + } + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "rows_estimation": [ + { + "table": "", + "table_scan": { + "rows": 2, + "cost": 2 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 2, + "cost": 2, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": null, + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [ + { + "join_execution": { + "select_id": 2, + "steps": [] + } + } + ] + } + } + ] +} 0 0 +drop table t1,t2; +drop view v1,v2; +drop function f1; +create table t1(a int, b int); +insert into t1 values (0,0),(1,1),(2,1),(3,2),(4,3), +(5,3),(6,3),(7,3),(8,3),(9,3); +create table t2(a int, b int); +insert into t2 values (0,0),(1,1),(2,1),(3,2),(4,3), +(5,3),(6,3),(7,3),(8,3),(9,3); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +create view v1 as select a from t1 group by b; +create view v2 as select a from t2; +# Mergeable view +explain select * from v2 ; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 10 +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain select * from v2 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "view": { + "table": "v2", + "select_id": 2, + "merged": true + } + }, + { + "join_preparation": { + "select_id": 2, + "steps": [ + { + "expanded_query": "/* select#2 */ select `t2`.`a` AS `a` from `t2`" + } + ] + } + }, + { + "expanded_query": "/* select#1 */ select `t2`.`a` AS `a` from `v2`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "table_dependencies": [ + { + "table": "t2", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "rows_estimation": [ + { + "table": "t2", + "table_scan": { + "rows": 10, + "cost": 2.022 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t2", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 10, + "cost": 2.022, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": null, + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t2", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +# Non-Mergeable view +explain select * from v1 ; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY ALL NULL NULL NULL NULL 10 +2 DERIVED t1 ALL NULL NULL NULL NULL 10 Using temporary; Using filesort +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain select * from v1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "view": { + "table": "v1", + "select_id": 2, + "materialized": true + } + }, + { + "join_preparation": { + "select_id": 2, + "steps": [ + { + "expanded_query": "/* select#2 */ select `t1`.`a` AS `a` from `t1` group by `t1`.`b`" + } + ] + } + }, + { + "expanded_query": "/* select#1 */ select `v1`.`a` AS `a` from `v1`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "join_optimization": { + "select_id": 2, + "steps": [ + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "rows_estimation": [ + { + "table": "t1", + "table_scan": { + "rows": 10, + "cost": 2.022 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 10, + "cost": 2.022, + "chosen": true, + "use_tmp_table": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": null, + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + } + ] + } + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "rows_estimation": [ + { + "table": "", + "table_scan": { + "rows": 10, + "cost": 10 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 10, + "cost": 10, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": null, + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [ + { + "join_execution": { + "select_id": 2, + "steps": [] + } + } + ] + } + } + ] +} 0 0 +drop table t1,t2; +drop view v1,v2; +# +# print ref-keyues array +# +create table t0 (a int); +INSERT INTO t0 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int, b int, c int, key(a)); +insert into t1 select A.a*10 + B.a, A.a*10 + B.a, A.a*10 + B.a from t0 A, t0 B; +create table t2(a int, b int, c int , key(a)); +insert into t2 select A.a*10 + B.a, A.a*10 + B.a, A.a*10 + B.a from t0 A, t0 B; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +analyze table t2; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status Table is already up to date +explain select * from t1,t2 where t1.a=t2.b+2 and t2.a= t1.b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL a NULL NULL NULL 100 Using where +1 SIMPLE t2 ref a a 5 test.t1.b 1 Using where +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain select * from t1,t2 where t1.a=t2.b+2 and t2.a= t1.b { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t2`.`a` AS `a`,`t2`.`b` AS `b`,`t2`.`c` AS `c` from `t1` join `t2` where `t1`.`a` = `t2`.`b` + 2 and `t2`.`a` = `t1`.`b`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.a = t2.b + 2 and t2.a = t1.b", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "t1.a = t2.b + 2 and multiple equal(t2.a, t1.b)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "t1.a = t2.b + 2 and multiple equal(t2.a, t1.b)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "t1.a = t2.b + 2 and multiple equal(t2.a, t1.b)" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + }, + { + "table": "t2", + "row_may_be_null": false, + "map_bit": 1, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [ + { + "table": "t1", + "field": "a", + "equals": "t2.b + 2", + "null_rejecting": false + }, + { + "table": "t2", + "field": "a", + "equals": "t1.b", + "null_rejecting": true + } + ] + }, + { + "rows_estimation": [ + { + "table": "t1", + "table_scan": { + "rows": 100, + "cost": 2.3174 + } + }, + { + "table": "t2", + "table_scan": { + "rows": 100, + "cost": 2.3174 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 100, + "cost": 2.3174, + "chosen": true + } + ] + }, + "rest_of_plan": [ + { + "plan_prefix": ["t1"], + "table": "t2", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "ref", + "index": "a", + "used_range_estimates": false, + "cause": "not available", + "rows": 1, + "cost": 200, + "chosen": true + }, + { + "access_type": "scan", + "resulting_rows": 100, + "cost": 2.3174, + "chosen": false + } + ] + } + } + ] + }, + { + "plan_prefix": [], + "table": "t2", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 100, + "cost": 2.3174, + "chosen": true + } + ] + }, + "rest_of_plan": [ + { + "plan_prefix": ["t2"], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "ref", + "index": "a", + "used_range_estimates": false, + "cause": "not available", + "rows": 1, + "cost": 200, + "chosen": true + }, + { + "access_type": "scan", + "resulting_rows": 100, + "cost": 2.3174, + "chosen": false + } + ] + }, + "pruned_by_cost": true + } + ] + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t2.a = t1.b and t1.a = t2.b + 2", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": "t1.b is not null" + }, + { + "table": "t2", + "attached": "t1.a = t2.b + 2" + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +drop table t1,t2,t0; +# +# group_by min max optimization +# +CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, a INT NOT NULL, KEY(a)); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +EXPLAIN SELECT DISTINCT a FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL a 4 NULL 5 Using index for group-by +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +EXPLAIN SELECT DISTINCT a FROM t1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select distinct `t1`.`a` AS `a` from `t1`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "rows_estimation": [ + { + "table": "t1", + "range_analysis": { + "table_scan": { + "rows": 65536, + "cost": 13255 + }, + "potential_range_indexes": [ + { + "index": "PRIMARY", + "usable": false, + "cause": "not applicable" + }, + { + "index": "a", + "usable": true, + "key_parts": ["a"] + } + ], + "best_covering_index_scan": { + "index": "a", + "cost": 14627, + "chosen": false, + "cause": "cost" + }, + "group_index_range": { + "distinct_query": true, + "potential_group_range_indexes": [ + { + "index": "a", + "covering": true, + "rows": 5, + "cost": 7.5 + } + ] + }, + "best_group_range_summary": { + "type": "index_group", + "index": "a", + "group_attribute": null, + "min_aggregate": false, + "max_aggregate": false, + "distinct_aggregate": false, + "rows": 5, + "cost": 7.5, + "key_parts_used_for_access": ["a"], + "ranges": [], + "chosen": true + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "index_group", + "index": "a", + "group_attribute": null, + "min_aggregate": false, + "max_aggregate": false, + "distinct_aggregate": false, + "rows": 5, + "cost": 7.5, + "key_parts_used_for_access": ["a"], + "ranges": [] + }, + "rows_for_plan": 5, + "cost_for_plan": 7.5, + "chosen": true + } + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "range", + "resulting_rows": 5, + "cost": 7.5, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": null, + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +drop table t1; +# +# With group by , where clause and MIN/MAX function +# +CREATE TABLE t1 (a INT, b INT, c int, d int, KEY(a,b,c,d)); +INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (1,0,1,1), (3,2,3,3), (4,5,4,4); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL a 20 NULL 7 Using where; Using index +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select min(`t1`.`d`) AS `MIN(d)` from `t1` where `t1`.`b` = 2 and `t1`.`c` = 3 group by `t1`.`a`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.b = 2 and t1.c = 3", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "multiple equal(2, t1.b) and multiple equal(3, t1.c)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "multiple equal(2, t1.b) and multiple equal(3, t1.c)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "multiple equal(2, t1.b) and multiple equal(3, t1.c)" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [] + }, + { + "rows_estimation": [ + { + "table": "t1", + "range_analysis": { + "table_scan": { + "rows": 7, + "cost": 5.5291 + }, + "potential_range_indexes": [ + { + "index": "a", + "usable": true, + "key_parts": ["a", "b", "c", "d"] + } + ], + "best_covering_index_scan": { + "index": "a", + "cost": 2.7006, + "chosen": true + }, + "setup_range_conditions": [], + "group_index_range": { + "potential_group_range_indexes": [ + { + "index": "a", + "covering": true, + "ranges": ["2 <= b <= 2 AND 3 <= c <= 3"], + "rows": 8, + "cost": 3.4 + } + ] + }, + "best_group_range_summary": { + "type": "index_group", + "index": "a", + "group_attribute": "d", + "min_aggregate": true, + "max_aggregate": false, + "distinct_aggregate": false, + "rows": 8, + "cost": 3.4, + "key_parts_used_for_access": ["a", "b", "c"], + "ranges": ["2 <= b <= 2 AND 3 <= c <= 3"], + "chosen": false, + "cause": "cost" + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [], + "analyzing_roworder_intersect": { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": [] + } + } + }, + { + "selectivity_for_indexes": [], + "selectivity_for_columns": [ + { + "column_name": "b", + "selectivity_from_histograms": 0.1667 + }, + { + "column_name": "c", + "selectivity_from_histograms": 0.25 + } + ] + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 0.2917, + "cost": 3.3707, + "chosen": true, + "use_tmp_table": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t1.b = 2 and t1.c = 3", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": "t1.b = 2 and t1.c = 3" + } + ] + } + }, + { + "reconsidering_access_paths_for_index_ordering": { + "clause": "GROUP BY", + "fanout": 1, + "read_time": 3.3717, + "table": "t1", + "rows_estimation": 7, + "possible_keys": [ + { + "index": "a", + "can_resolve_order": true, + "updated_limit": 7, + "index_scan_time": 7, + "records": 7, + "chosen": true + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +DROP TABLE t1; +CREATE TABLE t1 (id INT NOT NULL, a DATE, KEY(id,a)); +INSERT INTO t1 values (1,'2001-01-01'),(1,'2001-01-02'), +(1,'2001-01-03'),(1,'2001-01-04'), +(2,'2001-01-01'),(2,'2001-01-02'), +(2,'2001-01-03'),(2,'2001-01-04'), +(3,'2001-01-01'),(3,'2001-01-02'), +(3,'2001-01-03'),(3,'2001-01-04'), +(4,'2001-01-01'),(4,'2001-01-02'), +(4,'2001-01-03'),(4,'2001-01-04'); +set optimizer_trace='enabled=on'; +EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL id 8 NULL 9 Using where; Using index for group-by +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `t1`.`id` AS `id`,min(`t1`.`a`) AS `MIN(a)`,max(`t1`.`a`) AS `MAX(a)` from `t1` where `t1`.`a` >= 20010104e0 group by `t1`.`id`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.a >= 20010104e0", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "t1.a >= 20010104e0" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "t1.a >= 20010104e0" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "t1.a >= 20010104e0" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [] + }, + { + "rows_estimation": [ + { + "table": "t1", + "range_analysis": { + "table_scan": { + "rows": 16, + "cost": 7.3313 + }, + "potential_range_indexes": [ + { + "index": "id", + "usable": true, + "key_parts": ["id", "a"] + } + ], + "best_covering_index_scan": { + "index": "id", + "cost": 4.6269, + "chosen": true + }, + "setup_range_conditions": [], + "group_index_range": { + "potential_group_range_indexes": [ + { + "index": "id", + "covering": true, + "ranges": ["0x24a20f <= a"], + "rows": 9, + "cost": 3.7 + } + ] + }, + "best_group_range_summary": { + "type": "index_group", + "index": "id", + "group_attribute": "a", + "min_aggregate": true, + "max_aggregate": true, + "distinct_aggregate": false, + "rows": 9, + "cost": 3.7, + "key_parts_used_for_access": ["id"], + "ranges": ["0x24a20f <= a"], + "chosen": true + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [], + "analyzing_roworder_intersect": { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": [] + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "index_group", + "index": "id", + "group_attribute": "a", + "min_aggregate": true, + "max_aggregate": true, + "distinct_aggregate": false, + "rows": 9, + "cost": 3.7, + "key_parts_used_for_access": ["id"], + "ranges": ["0x24a20f <= a"] + }, + "rows_for_plan": 9, + "cost_for_plan": 3.7, + "chosen": true + } + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "range", + "resulting_rows": 9, + "cost": 3.7, + "chosen": true, + "use_tmp_table": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t1.a >= 20010104e0", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": "t1.a >= 20010104e0" + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL id 8 NULL 9 Using where; Using index for group-by +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `t1`.`id` AS `id`,`t1`.`a` AS `a` from `t1` where `t1`.`a` = 20010104e0 group by `t1`.`id`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.a = 20010104e0", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "t1.a = 20010104e0" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "t1.a = 20010104e0" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "t1.a = 20010104e0" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [] + }, + { + "rows_estimation": [ + { + "table": "t1", + "range_analysis": { + "table_scan": { + "rows": 16, + "cost": 7.3313 + }, + "potential_range_indexes": [ + { + "index": "id", + "usable": true, + "key_parts": ["id", "a"] + } + ], + "best_covering_index_scan": { + "index": "id", + "cost": 4.6269, + "chosen": true + }, + "setup_range_conditions": [], + "group_index_range": { + "potential_group_range_indexes": [ + { + "index": "id", + "covering": true, + "ranges": ["0x24a20f <= a <= 0x24a20f"], + "rows": 9, + "cost": 3.7 + } + ] + }, + "best_group_range_summary": { + "type": "index_group", + "index": "id", + "group_attribute": null, + "min_aggregate": false, + "max_aggregate": false, + "distinct_aggregate": false, + "rows": 9, + "cost": 3.7, + "key_parts_used_for_access": ["id", "a"], + "ranges": ["0x24a20f <= a <= 0x24a20f"], + "chosen": true + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [], + "analyzing_roworder_intersect": { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": [] + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "index_group", + "index": "id", + "group_attribute": null, + "min_aggregate": false, + "max_aggregate": false, + "distinct_aggregate": false, + "rows": 9, + "cost": 3.7, + "key_parts_used_for_access": ["id", "a"], + "ranges": ["0x24a20f <= a <= 0x24a20f"] + }, + "rows_for_plan": 9, + "cost_for_plan": 3.7, + "chosen": true + } + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "range", + "resulting_rows": 9, + "cost": 3.7, + "chosen": true, + "use_tmp_table": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t1.a = 20010104e0", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": "t1.a = 20010104e0" + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +drop table t1; +# +# Late ORDER BY optimization +# +create table ten(a int); +insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table one_k(a int primary key); +insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C; +create table t1 ( +pk int not null, +a int, +b int, +c int, +filler char(100), +KEY a_a(c), +KEY a_c(a,c), +KEY a_b(a,b) +); +insert into t1 +select a, a,a,a, 'filler-dataaa' from test.one_k; +update t1 set a=1 where pk between 0 and 180; +update t1 set b=2 where pk between 0 and 20; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +set optimizer_trace='enabled=on'; +explain select * from t1 where a=1 and b=2 order by c limit 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range a_c,a_b a_c 5 NULL 180 Using where +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain select * from t1 where a=1 and b=2 order by c limit 1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `t1`.`pk` AS `pk`,`t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t1`.`filler` AS `filler` from `t1` where `t1`.`a` = 1 and `t1`.`b` = 2 order by `t1`.`c` limit 1" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.a = 1 and t1.b = 2", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "multiple equal(1, t1.a) and multiple equal(2, t1.b)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "multiple equal(1, t1.a) and multiple equal(2, t1.b)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "multiple equal(1, t1.a) and multiple equal(2, t1.b)" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [ + { + "table": "t1", + "field": "a", + "equals": "1", + "null_rejecting": false + }, + { + "table": "t1", + "field": "a", + "equals": "1", + "null_rejecting": false + }, + { + "table": "t1", + "field": "b", + "equals": "2", + "null_rejecting": false + } + ] + }, + { + "rows_estimation": [ + { + "table": "t1", + "range_analysis": { + "table_scan": { + "rows": 1000, + "cost": 232.66 + }, + "potential_range_indexes": [ + { + "index": "a_a", + "usable": false, + "cause": "not applicable" + }, + { + "index": "a_c", + "usable": true, + "key_parts": ["a", "c"] + }, + { + "index": "a_b", + "usable": true, + "key_parts": ["a", "b"] + } + ], + "setup_range_conditions": [], + "group_index_range": { + "chosen": false, + "cause": "no group by or distinct" + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [ + { + "index": "a_c", + "ranges": ["1 <= a <= 1"], + "rowid_ordered": false, + "using_mrr": false, + "index_only": false, + "rows": 180, + "cost": 217.01, + "chosen": true + }, + { + "index": "a_b", + "ranges": ["1 <= a <= 1 AND 2 <= b <= 2"], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 21, + "cost": 26.21, + "chosen": true + } + ], + "analyzing_roworder_intersect": { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": [] + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "range_scan", + "index": "a_b", + "rows": 21, + "ranges": ["1 <= a <= 1 AND 2 <= b <= 2"] + }, + "rows_for_plan": 21, + "cost_for_plan": 26.21, + "chosen": true + } + } + }, + { + "selectivity_for_indexes": [ + { + "index_name": "a_b", + "selectivity_from_index": 0.021 + } + ], + "selectivity_for_columns": [ + { + "column_name": "a", + "selectivity_from_histograms": 0.0012 + }, + { + "column_name": "b", + "selectivity_from_histograms": 0.001 + } + ] + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "ref", + "index": "a_c", + "used_range_estimates": true, + "rows": 180, + "cost": 92, + "chosen": true + }, + { + "access_type": "ref", + "index": "a_b", + "used_range_estimates": true, + "rows": 21, + "cost": 22, + "chosen": true + }, + { + "type": "scan", + "chosen": false, + "cause": "cost" + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t1.a = 1 and t1.b = 2", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + } + ] + } + }, + { + "reconsidering_access_paths_for_index_ordering": { + "clause": "ORDER BY", + "fanout": 1, + "read_time": 22.001, + "table": "t1", + "rows_estimation": 21, + "possible_keys": [ + { + "index": "a_a", + "can_resolve_order": true, + "updated_limit": 47, + "index_scan_time": 47, + "usable": false, + "cause": "cost" + }, + { + "index": "a_c", + "can_resolve_order": true, + "updated_limit": 47, + "range_scan_time": 4.324, + "index_scan_time": 4.324, + "records": 180, + "chosen": true + }, + { + "index": "a_b", + "can_resolve_order": false, + "cause": "not usable index for the query" + } + ] + } + }, + { + "table": "t1", + "range_analysis": { + "table_scan": { + "rows": 1000, + "cost": 1202 + }, + "potential_range_indexes": [ + { + "index": "a_a", + "usable": false, + "cause": "not applicable" + }, + { + "index": "a_c", + "usable": true, + "key_parts": ["a", "c"] + }, + { + "index": "a_b", + "usable": false, + "cause": "not applicable" + } + ], + "setup_range_conditions": [], + "group_index_range": { + "chosen": false, + "cause": "no group by or distinct" + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [ + { + "index": "a_c", + "ranges": ["1 <= a <= 1"], + "rowid_ordered": false, + "using_mrr": false, + "index_only": false, + "rows": 180, + "cost": 217.01, + "chosen": true + } + ], + "analyzing_roworder_intersect": { + "cause": "too few roworder scans" + }, + "analyzing_index_merge_union": [] + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "range_scan", + "index": "a_c", + "rows": 180, + "ranges": ["1 <= a <= 1"] + }, + "rows_for_plan": 180, + "cost_for_plan": 217.01, + "chosen": true + } + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +drop table t1,ten,one_k; +# +# TABLE ELIMINATION +# +create table t1 (a int); +insert into t1 values (0),(1),(2),(3); +create table t0 as select * from t1; +create table t2 (a int primary key, b int) +as select a, a as b from t1 where a in (1,2); +create table t3 (a int primary key, b int) +as select a, a as b from t1 where a in (1,3); +set optimizer_trace='enabled=on'; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +analyze table t2; +Table Op Msg_type Msg_text +test.t2 analyze status Engine-independent statistics collected +test.t2 analyze status OK +analyze table t3; +Table Op Msg_type Msg_text +test.t3 analyze status Engine-independent statistics collected +test.t3 analyze status OK +# table t2 should be eliminated +explain +select t1.a from t1 left join t2 on t1.a=t2.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain +select t1.a from t1 left join t2 on t1.a=t2.a { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `t1`.`a` AS `a` from (`t1` left join `t2` on(`t1`.`a` = `t2`.`a`))" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + }, + { + "table": "t2", + "row_may_be_null": true, + "map_bit": 1, + "depends_on_map_bits": ["0"] + } + ] + }, + { + "ref_optimizer_key_uses": [ + { + "table": "t2", + "field": "a", + "equals": "t1.a", + "null_rejecting": true + } + ] + }, + { + "eliminated_tables": ["t2"] + }, + { + "rows_estimation": [ + { + "table": "t1", + "table_scan": { + "rows": 4, + "cost": 2.0068 + } + }, + { + "table": "t2", + "rows": 1, + "cost": 1, + "table_type": "const" + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": ["t2"], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 4, + "cost": 2.0068, + "chosen": true + } + ] + } + } + ] + }, + { + "condition_on_constant_tables": "1" + }, + { + "attaching_conditions_to_tables": { + "original_condition": "1", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +# no tables should be eliminated +explain select * from t1 left join t2 on t2.a=t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using where +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain select * from t1 left join t2 on t2.a=t1.a { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `t1`.`a` AS `a`,`t2`.`a` AS `a`,`t2`.`b` AS `b` from (`t1` left join `t2` on(`t2`.`a` = `t1`.`a`))" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + }, + { + "table": "t2", + "row_may_be_null": true, + "map_bit": 1, + "depends_on_map_bits": ["0"] + } + ] + }, + { + "ref_optimizer_key_uses": [ + { + "table": "t2", + "field": "a", + "equals": "t1.a", + "null_rejecting": true + } + ] + }, + { + "eliminated_tables": [] + }, + { + "rows_estimation": [ + { + "table": "t1", + "table_scan": { + "rows": 4, + "cost": 2.0068 + } + }, + { + "table": "t2", + "table_scan": { + "rows": 2, + "cost": 2.0044 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 4, + "cost": 2.0068, + "chosen": true + } + ] + }, + "rest_of_plan": [ + { + "plan_prefix": ["t1"], + "table": "t2", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "eq_ref", + "index": "PRIMARY", + "rows": 1, + "cost": 4, + "chosen": true + }, + { + "access_type": "scan", + "resulting_rows": 2, + "cost": 8.0176, + "chosen": false + } + ] + } + } + ] + } + ] + }, + { + "condition_on_constant_tables": "1" + }, + { + "attaching_conditions_to_tables": { + "original_condition": "1", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + }, + { + "table": "t2", + "attached": "trigcond(trigcond(t1.a is not null))" + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +# multiple tables are eliminated +explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and t3.a=t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and t3.a=t1.a { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `t1`.`a` AS `a` from (`t1` left join (`t2` join `t3` on(`t2`.`b` = `t3`.`b`)) on(`t2`.`a` = `t1`.`a` and `t3`.`a` = `t1`.`a`))" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + }, + { + "table": "t2", + "row_may_be_null": true, + "map_bit": 1, + "depends_on_map_bits": ["0"] + }, + { + "table": "t3", + "row_may_be_null": true, + "map_bit": 2, + "depends_on_map_bits": ["0"] + } + ] + }, + { + "ref_optimizer_key_uses": [ + { + "table": "t2", + "field": "a", + "equals": "t1.a", + "null_rejecting": true + }, + { + "table": "t2", + "field": "a", + "equals": "t3.a", + "null_rejecting": true + }, + { + "table": "t3", + "field": "a", + "equals": "t2.a", + "null_rejecting": true + }, + { + "table": "t3", + "field": "a", + "equals": "t1.a", + "null_rejecting": true + } + ] + }, + { + "eliminated_tables": ["t3", "t2"] + }, + { + "rows_estimation": [ + { + "table": "t1", + "table_scan": { + "rows": 4, + "cost": 2.0068 + } + }, + { + "table": "t2", + "rows": 1, + "cost": 1, + "table_type": "const" + }, + { + "table": "t3", + "rows": 1, + "cost": 1, + "table_type": "const" + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": ["t3", "t2"], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 4, + "cost": 2.0068, + "chosen": true + } + ] + } + } + ] + }, + { + "condition_on_constant_tables": "1" + }, + { + "attaching_conditions_to_tables": { + "original_condition": "1", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +drop table t0, t1, t2, t3; +# +# IN subquery to sem-join is traced +# +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1(a int, b int); +insert into t1 values (0,0),(1,1),(2,2); +create table t2 as select * from t1; +create table t11(a int, b int); +create table t10 (pk int, a int); +insert into t10 select a,a from t0; +create table t12 like t10; +insert into t12 select * from t10; +analyze table t1,t10; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +test.t10 analyze status Engine-independent statistics collected +test.t10 analyze status OK +set optimizer_trace='enabled=on'; +explain extended select * from t1 where a in (select pk from t10); +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 +1 PRIMARY eq_ref distinct_key distinct_key 4 func 1 100.00 +2 MATERIALIZED t10 ALL NULL NULL NULL NULL 10 100.00 +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` semi join (`test`.`t10`) where 1 +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain extended select * from t1 where a in (select pk from t10) { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "join_preparation": { + "select_id": 2, + "steps": [ + { + "transformation": { + "select_id": 2, + "from": "IN (SELECT)", + "to": "materialization", + "sjm_scan_allowed": true, + "possible": true + } + }, + { + "transformation": { + "select_id": 2, + "from": "IN (SELECT)", + "to": "semijoin", + "chosen": true + } + }, + { + "expanded_query": "/* select#2 */ select `t10`.`pk` from `t10`" + } + ] + } + }, + { + "expanded_query": "/* select#1 */ select `t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`a` in (/* select#2 */ select `t10`.`pk` from `t10`)" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "transformation": { + "select_id": 2, + "from": "IN (SELECT)", + "to": "semijoin", + "converted_to_semi_join": true + } + }, + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "1 and t1.a = t10.pk", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "1 and multiple equal(t1.a, t10.pk)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "1 and multiple equal(t1.a, t10.pk)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "multiple equal(t1.a, t10.pk)" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + }, + { + "table": "t10", + "row_may_be_null": false, + "map_bit": 1, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [] + }, + { + "rows_estimation": [ + { + "table": "t1", + "table_scan": { + "rows": 3, + "cost": 2.0066 + } + }, + { + "table": "t10", + "table_scan": { + "rows": 10, + "cost": 2.022 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [ + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t10", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 10, + "cost": 2.022, + "chosen": true + } + ] + } + } + ] + } + ] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 3, + "cost": 2.0066, + "chosen": true + } + ] + }, + "rest_of_plan": [ + { + "plan_prefix": ["t1"], + "table": "t10", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 10, + "cost": 2.022, + "chosen": true + } + ] + } + } + ] + }, + { + "plan_prefix": [], + "table": "t10", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 10, + "cost": 2.022, + "chosen": true + } + ] + }, + "pruned_by_heuristic": true + } + ] + }, + { + "condition_on_constant_tables": "1" + }, + { + "attaching_conditions_to_tables": { + "original_condition": "1", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + }, + { + "table": "t10", + "attached": null + }, + { + "table": "", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +drop table t0,t1,t11,t10,t12,t2; +# +# Selectivities for columns and indexes. +# +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 ( +pk int, +a int, +b int, +key pk(pk), +key pk_a(pk,a), +key pk_a_b(pk,a,b)); +insert into t1 select a,a,a from t0; +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS (a,b) INDEXES (); +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status Table is already up to date +set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity; +set @save_use_stat_tables= @@use_stat_tables; +set @@optimizer_use_condition_selectivity=4; +set @@use_stat_tables= PREFERABLY; +set optimizer_trace='enabled=on'; +explain select * from t1 where pk = 2 and a=5 and b=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref pk,pk_a,pk_a_b pk_a_b 15 const,const,const 1 Using index +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain select * from t1 where pk = 2 and a=5 and b=1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `t1`.`pk` AS `pk`,`t1`.`a` AS `a`,`t1`.`b` AS `b` from `t1` where `t1`.`pk` = 2 and `t1`.`a` = 5 and `t1`.`b` = 1" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.pk = 2 and t1.a = 5 and t1.b = 1", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "multiple equal(2, t1.pk) and multiple equal(5, t1.a) and multiple equal(1, t1.b)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "multiple equal(2, t1.pk) and multiple equal(5, t1.a) and multiple equal(1, t1.b)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "multiple equal(2, t1.pk) and multiple equal(5, t1.a) and multiple equal(1, t1.b)" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [ + { + "table": "t1", + "field": "pk", + "equals": "2", + "null_rejecting": false + }, + { + "table": "t1", + "field": "pk", + "equals": "2", + "null_rejecting": false + }, + { + "table": "t1", + "field": "a", + "equals": "5", + "null_rejecting": false + }, + { + "table": "t1", + "field": "pk", + "equals": "2", + "null_rejecting": false + }, + { + "table": "t1", + "field": "a", + "equals": "5", + "null_rejecting": false + }, + { + "table": "t1", + "field": "b", + "equals": "1", + "null_rejecting": false + } + ] + }, + { + "rows_estimation": [ + { + "table": "t1", + "range_analysis": { + "table_scan": { + "rows": 10, + "cost": 6.1317 + }, + "potential_range_indexes": [ + { + "index": "pk", + "usable": true, + "key_parts": ["pk"] + }, + { + "index": "pk_a", + "usable": true, + "key_parts": ["pk", "a"] + }, + { + "index": "pk_a_b", + "usable": true, + "key_parts": ["pk", "a", "b"] + } + ], + "best_covering_index_scan": { + "index": "pk_a_b", + "cost": 3.3708, + "chosen": true + }, + "setup_range_conditions": [], + "group_index_range": { + "chosen": false, + "cause": "no group by or distinct" + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [ + { + "index": "pk", + "ranges": ["2 <= pk <= 2"], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 1, + "cost": 2.21, + "chosen": true + }, + { + "index": "pk_a", + "ranges": ["2 <= pk <= 2 AND 5 <= a <= 5"], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 1, + "cost": 2.21, + "chosen": false, + "cause": "cost" + }, + { + "index": "pk_a_b", + "ranges": ["2 <= pk <= 2 AND 5 <= a <= 5 AND 1 <= b <= 1"], + "rowid_ordered": true, + "using_mrr": false, + "index_only": true, + "rows": 1, + "cost": 2.21, + "chosen": false, + "cause": "cost" + } + ], + "analyzing_roworder_intersect": { + "intersecting_indexes": [ + { + "index": "pk", + "index_scan_cost": 1, + "cumulateed_index_scan_cost": 1, + "disk_sweep_cost": 0.9008, + "cumulative_total_cost": 1.9008, + "usable": true, + "matching_rows_now": 1, + "intersect_covering_with_this_index": false, + "chosen": true + }, + { + "index": "pk_a", + "usable": false, + "cause": "does not reduce cost of intersect" + }, + { + "index": "pk_a_b", + "usable": false, + "cause": "does not reduce cost of intersect" + } + ], + "clustered_pk": { + "clustered_pk_added_to_intersect": false, + "cause": "no clustered pk index" + }, + "chosen": false, + "cause": "too few indexes to merge" + }, + "analyzing_index_merge_union": [] + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "range_scan", + "index": "pk", + "rows": 1, + "ranges": ["2 <= pk <= 2"] + }, + "rows_for_plan": 1, + "cost_for_plan": 2.21, + "chosen": true + } + } + }, + { + "selectivity_for_indexes": [ + { + "index_name": "pk_a_b", + "selectivity_from_index": 0.1 + } + ], + "selectivity_for_columns": [ + { + "column_name": "a", + "selectivity_from_histograms": 0.1 + }, + { + "column_name": "b", + "selectivity_from_histograms": 0.1 + } + ] + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "ref", + "index": "pk", + "used_range_estimates": true, + "rows": 1, + "cost": 2, + "chosen": true + }, + { + "access_type": "ref", + "index": "pk_a", + "used_range_estimates": true, + "rows": 1, + "cost": 2, + "chosen": false, + "cause": "cost" + }, + { + "access_type": "ref", + "index": "pk_a_b", + "used_range_estimates": true, + "rows": 1, + "cost": 1, + "chosen": true + }, + { + "access_type": "range", + "resulting_rows": 1, + "cost": 2.21, + "chosen": false + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t1.pk = 2 and t1.a = 5 and t1.b = 1", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; +set @@use_stat_tables= @save_use_stat_tables; +drop table t0,t1; +set optimizer_trace="enabled=off"; +# +# Tests added to show that sub-statements are not traced +# +create table t1(a int); +insert into t1 values (1),(2),(3),(4); +create table t2(a int); +insert into t2 values (1),(2),(3),(4); +create function f1(a int) returns int +begin +declare a int default 0; +set a= a+ (select count(*) from t2); +return a; +end| +create function f2(a int) returns int +begin +declare a int default 0; +select count(*) from t2 into a; +return a; +end| +Warnings: +Warning 1287 ' INTO FROM...' instead +set optimizer_trace='enabled=on'; +select f1(a) from t1; +f1(a) +4 +4 +4 +4 +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +select f1(a) from t1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `f1`(`t1`.`a`) AS `f1(a)` from `t1`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "rows_estimation": [ + { + "table": "t1", + "table_scan": { + "rows": 4, + "cost": 2.0068 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 4, + "cost": 2.0068, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": null, + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +select f2(a) from t1; +f2(a) +4 +4 +4 +4 +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +select f2(a) from t1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `f2`(`t1`.`a`) AS `f2(a)` from `t1`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "rows_estimation": [ + { + "table": "t1", + "table_scan": { + "rows": 4, + "cost": 2.0068 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 4, + "cost": 2.0068, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": null, + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +drop table t1,t2; +drop function f1; +drop function f2; +set optimizer_trace='enabled=off'; +# +# MDEV-18489: Limit the memory used by the optimizer trace +# +create table t1 (a int); +insert into t1 values (1),(2); +set optimizer_trace='enabled=on'; +set @save_optimizer_trace_max_mem_size= @@optimizer_trace_max_mem_size; +select * from t1; +a +1 +2 +select length(trace) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +length(trace) +1889 +set optimizer_trace_max_mem_size=100; +select * from t1; +a +1 +2 +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +select * from t1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + 1789 0 +set optimizer_trace_max_mem_size=0; +select * from t1; +a +1 +2 +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +select * from t1 1889 0 +drop table t1; +set optimizer_trace='enabled=off'; +set @@optimizer_trace_max_mem_size= @save_optimizer_trace_max_mem_size; +# +# MDEV-18527: Optimizer trace for DELETE query shows table:null +# +create table ten(a int); +insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t0 (a int, b int); +insert into t0 select a,a from ten; +alter table t0 add key(a); +set optimizer_trace=1; +explain delete from t0 where t0.a<3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 range a a 5 NULL 3 Using where +select * from information_schema.optimizer_trace; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain delete from t0 where t0.a<3 { + "steps": [ + { + "table": "t0", + "range_analysis": { + "table_scan": { + "rows": 10, + "cost": 6.122 + }, + "potential_range_indexes": [ + { + "index": "a", + "usable": true, + "key_parts": ["a"] + } + ], + "setup_range_conditions": [], + "group_index_range": { + "chosen": false, + "cause": "no join" + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [ + { + "index": "a", + "ranges": ["NULL < a < 3"], + "rowid_ordered": false, + "using_mrr": false, + "index_only": false, + "rows": 3, + "cost": 4.61, + "chosen": true + } + ], + "analyzing_index_merge_union": [] + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "range_scan", + "index": "a", + "rows": 3, + "ranges": ["NULL < a < 3"] + }, + "rows_for_plan": 3, + "cost_for_plan": 4.61, + "chosen": true + } + } + } + ] +} 0 0 +drop table ten,t0; +set optimizer_trace='enabled=off'; +# +# MDEV-18528: Optimizer trace support for multi-table UPDATE and DELETE +# +create table ten(a int); +insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t0 (a int, b int); +insert into t0 select a,a from ten; +alter table t0 add key(a); +create table t1 like t0; +insert into t1 select * from t0; +explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t0 range a a 5 NULL 3 Using where +1 SIMPLE t1 ref a a 5 test.t0.a 1 +select * from information_schema.optimizer_trace; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain delete from t0 where t0.a<3 { + "steps": [ + { + "table": "t0", + "range_analysis": { + "table_scan": { + "rows": 10, + "cost": 6.122 + }, + "potential_range_indexes": [ + { + "index": "a", + "usable": true, + "key_parts": ["a"] + } + ], + "setup_range_conditions": [], + "group_index_range": { + "chosen": false, + "cause": "no join" + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [ + { + "index": "a", + "ranges": ["NULL < a < 3"], + "rowid_ordered": false, + "using_mrr": false, + "index_only": false, + "rows": 3, + "cost": 4.61, + "chosen": true + } + ], + "analyzing_index_merge_union": [] + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "range_scan", + "index": "a", + "rows": 3, + "ranges": ["NULL < a < 3"] + }, + "rows_for_plan": 3, + "cost_for_plan": 4.61, + "chosen": true + } + } + } + ] +} 0 0 +drop table ten,t0,t1; diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test new file mode 100644 index 00000000000..f55cf57b82a --- /dev/null +++ b/mysql-test/main/opt_trace.test @@ -0,0 +1,335 @@ +--source include/not_embedded.inc +SELECT table_name, column_name FROM information_schema.columns where table_name="OPTIMIZER_TRACE"; +show variables like 'optimizer_trace'; +set optimizer_trace="enabled=on"; +show variables like 'optimizer_trace'; +set optimizer_trace="enabled=off"; +create table t1 (a int, b int); +insert into t1 values (1,2),(2,3); + +create table t2 (b int); +insert into t2 values (1),(2); + +analyze table t1; +analyze table t2; +create function f1 (a int) returns INT +return 1; + +create view v1 as select * from t1 where t1.a=1; +create view v2 as select * from t1 where t1.a=1 group by t1.b; +set optimizer_trace="enabled=on"; + +--echo # Mergeable views/derived tables +select * from v1; +select * from information_schema.OPTIMIZER_TRACE; +select * from (select * from t1 where t1.a=1)q; +select * from information_schema.OPTIMIZER_TRACE; + +--echo # Non-Mergeable views +select * from v2; +select * from information_schema.OPTIMIZER_TRACE; + +drop table t1,t2; +drop view v1,v2; +drop function f1; + +create table t1(a int, b int); +insert into t1 values (0,0),(1,1),(2,1),(3,2),(4,3), +(5,3),(6,3),(7,3),(8,3),(9,3); +create table t2(a int, b int); +insert into t2 values (0,0),(1,1),(2,1),(3,2),(4,3), +(5,3),(6,3),(7,3),(8,3),(9,3); + +ANALYZE TABLE t1; +ANALYZE TABLE t2; + +create view v1 as select a from t1 group by b; +create view v2 as select a from t2; + +--echo # Mergeable view +explain select * from v2 ; +select * from information_schema.OPTIMIZER_TRACE; + +--echo # Non-Mergeable view +explain select * from v1 ; +select * from information_schema.OPTIMIZER_TRACE; +drop table t1,t2; +drop view v1,v2; + +--echo # +--echo # print ref-keyues array +--echo # + +create table t0 (a int); +INSERT INTO t0 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t1 (a int, b int, c int, key(a)); +insert into t1 select A.a*10 + B.a, A.a*10 + B.a, A.a*10 + B.a from t0 A, t0 B; + +create table t2(a int, b int, c int , key(a)); +insert into t2 select A.a*10 + B.a, A.a*10 + B.a, A.a*10 + B.a from t0 A, t0 B; + +analyze table t1; +analyze table t2; + +explain select * from t1,t2 where t1.a=t2.b+2 and t2.a= t1.b; +select * from information_schema.OPTIMIZER_TRACE; +drop table t1,t2,t0; + +--echo # +--echo # group_by min max optimization +--echo # +CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, a INT NOT NULL, KEY(a)); +--disable_query_log +INSERT INTO t1(a) VALUES (1), (2), (3), (4); +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +INSERT INTO t1(a) SELECT a FROM t1; +--enable_query_log + +analyze table t1; +EXPLAIN SELECT DISTINCT a FROM t1; +select * from information_schema.OPTIMIZER_TRACE; +drop table t1; + +--echo # +--echo # With group by , where clause and MIN/MAX function +--echo # +CREATE TABLE t1 (a INT, b INT, c int, d int, KEY(a,b,c,d)); +INSERT INTO t1 VALUES (1,1,1,1), (2,2,2,2), (3,3,3,3), (4,4,4,4), (1,0,1,1), (3,2,3,3), (4,5,4,4); +ANALYZE TABLE t1; +EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a; +select * from information_schema.OPTIMIZER_TRACE; +DROP TABLE t1; + +CREATE TABLE t1 (id INT NOT NULL, a DATE, KEY(id,a)); +INSERT INTO t1 values (1,'2001-01-01'),(1,'2001-01-02'), + (1,'2001-01-03'),(1,'2001-01-04'), + (2,'2001-01-01'),(2,'2001-01-02'), + (2,'2001-01-03'),(2,'2001-01-04'), + (3,'2001-01-01'),(3,'2001-01-02'), + (3,'2001-01-03'),(3,'2001-01-04'), + (4,'2001-01-01'),(4,'2001-01-02'), + (4,'2001-01-03'),(4,'2001-01-04'); +set optimizer_trace='enabled=on'; +EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1; + +--echo # +--echo # Late ORDER BY optimization +--echo # + +create table ten(a int); +insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table one_k(a int primary key); +insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C; +create table t1 ( + pk int not null, + a int, + b int, + c int, + filler char(100), + KEY a_a(c), + KEY a_c(a,c), + KEY a_b(a,b) +); + +insert into t1 +select a, a,a,a, 'filler-dataaa' from test.one_k; +update t1 set a=1 where pk between 0 and 180; +update t1 set b=2 where pk between 0 and 20; +analyze table t1; +set optimizer_trace='enabled=on'; +explain select * from t1 where a=1 and b=2 order by c limit 1; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1,ten,one_k; + +--echo # +--echo # TABLE ELIMINATION +--echo # + +create table t1 (a int); +insert into t1 values (0),(1),(2),(3); +create table t0 as select * from t1; + +create table t2 (a int primary key, b int) + as select a, a as b from t1 where a in (1,2); + +create table t3 (a int primary key, b int) + as select a, a as b from t1 where a in (1,3); + +set optimizer_trace='enabled=on'; + +analyze table t1; +analyze table t2; +analyze table t3; + +--echo # table t2 should be eliminated +explain +select t1.a from t1 left join t2 on t1.a=t2.a; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; + +--echo # no tables should be eliminated +explain select * from t1 left join t2 on t2.a=t1.a; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; + +--echo # multiple tables are eliminated +explain select t1.a from t1 left join (t2 join t3 on t2.b=t3.b) on t2.a=t1.a and t3.a=t1.a; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t0, t1, t2, t3; + +--echo # +--echo # IN subquery to sem-join is traced +--echo # + +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t1(a int, b int); +insert into t1 values (0,0),(1,1),(2,2); +create table t2 as select * from t1; + +create table t11(a int, b int); + +create table t10 (pk int, a int); +insert into t10 select a,a from t0; +create table t12 like t10; +insert into t12 select * from t10; + +analyze table t1,t10; + +set optimizer_trace='enabled=on'; +explain extended select * from t1 where a in (select pk from t10); +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t0,t1,t11,t10,t12,t2; + +--echo # +--echo # Selectivities for columns and indexes. +--echo # + +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t1 ( +pk int, +a int, +b int, +key pk(pk), +key pk_a(pk,a), +key pk_a_b(pk,a,b)); +insert into t1 select a,a,a from t0; + +ANALYZE TABLE t1 PERSISTENT FOR COLUMNS (a,b) INDEXES (); +set @save_optimizer_use_condition_selectivity=@@optimizer_use_condition_selectivity; +set @save_use_stat_tables= @@use_stat_tables; +set @@optimizer_use_condition_selectivity=4; +set @@use_stat_tables= PREFERABLY; +set optimizer_trace='enabled=on'; +explain select * from t1 where pk = 2 and a=5 and b=1; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; +set @@use_stat_tables= @save_use_stat_tables; +drop table t0,t1; +set optimizer_trace="enabled=off"; + +--echo # +--echo # Tests added to show that sub-statements are not traced +--echo # + +create table t1(a int); +insert into t1 values (1),(2),(3),(4); +create table t2(a int); +insert into t2 values (1),(2),(3),(4); +delimiter |; +create function f1(a int) returns int +begin + declare a int default 0; + set a= a+ (select count(*) from t2); + return a; +end| + +create function f2(a int) returns int +begin + declare a int default 0; + select count(*) from t2 into a; + return a; +end| + +delimiter ;| +set optimizer_trace='enabled=on'; +select f1(a) from t1; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +select f2(a) from t1; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1,t2; +drop function f1; +drop function f2; +set optimizer_trace='enabled=off'; + +--echo # +--echo # MDEV-18489: Limit the memory used by the optimizer trace +--echo # + +create table t1 (a int); +insert into t1 values (1),(2); + +set optimizer_trace='enabled=on'; +set @save_optimizer_trace_max_mem_size= @@optimizer_trace_max_mem_size; +select * from t1; +select length(trace) from INFORMATION_SCHEMA.OPTIMIZER_TRACE; + +set optimizer_trace_max_mem_size=100; +select * from t1; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; + +set optimizer_trace_max_mem_size=0; +select * from t1; +select * from INFORMATION_SCHEMA.OPTIMIZER_TRACE; +drop table t1; +set optimizer_trace='enabled=off'; +set @@optimizer_trace_max_mem_size= @save_optimizer_trace_max_mem_size; + +--echo # +--echo # MDEV-18527: Optimizer trace for DELETE query shows table:null +--echo # + +create table ten(a int); +insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t0 (a int, b int); +insert into t0 select a,a from ten; +alter table t0 add key(a); + +set optimizer_trace=1; +explain delete from t0 where t0.a<3; +select * from information_schema.optimizer_trace; +drop table ten,t0; +set optimizer_trace='enabled=off'; + +--echo # +--echo # MDEV-18528: Optimizer trace support for multi-table UPDATE and DELETE +--echo # + +create table ten(a int); +insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t0 (a int, b int); +insert into t0 select a,a from ten; +alter table t0 add key(a); +create table t1 like t0; +insert into t1 select * from t0; +explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3; +select * from information_schema.optimizer_trace; +drop table ten,t0,t1; diff --git a/mysql-test/main/opt_trace_index_merge.result b/mysql-test/main/opt_trace_index_merge.result new file mode 100644 index 00000000000..4c75465f958 --- /dev/null +++ b/mysql-test/main/opt_trace_index_merge.result @@ -0,0 +1,249 @@ +set @tmp_opt_switch= @@optimizer_switch; +set optimizer_switch='index_merge_sort_intersection=on'; +set optimizer_trace='enabled=on'; +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int, b int, c int, filler char(100), +key(a), key(b), key(c)); +insert into t1 select +A.a * B.a*10 + C.a*100, +A.a * B.a*10 + C.a*100, +A.a, +'filler' +from t0 A, t0 B, t0 C; +This should use union: +explain select * from t1 where a=1 or b=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 2 Using union(a,b); Using where +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain select * from t1 where a=1 or b=1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `t1`.`a` AS `a`,`t1`.`b` AS `b`,`t1`.`c` AS `c`,`t1`.`filler` AS `filler` from `t1` where `t1`.`a` = 1 or `t1`.`b` = 1" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.a = 1 or t1.b = 1", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "multiple equal(1, t1.a) or multiple equal(1, t1.b)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "multiple equal(1, t1.a) or multiple equal(1, t1.b)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "multiple equal(1, t1.a) or multiple equal(1, t1.b)" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [] + }, + { + "rows_estimation": [ + { + "table": "t1", + "range_analysis": { + "table_scan": { + "rows": 1000, + "cost": 231.69 + }, + "potential_range_indexes": [ + { + "index": "a", + "usable": true, + "key_parts": ["a"] + }, + { + "index": "b", + "usable": true, + "key_parts": ["b"] + }, + { + "index": "c", + "usable": false, + "cause": "not applicable" + } + ], + "setup_range_conditions": [], + "group_index_range": { + "chosen": false, + "cause": "no group by or distinct" + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [], + "analyzing_roworder_intersect": { + "cause": "too few roworder scans" + }, + "analyzing_sort_intersect": {}, + "analyzing_index_merge_union": [ + { + "indexes_to_merge": [ + { + "range_scan_alternatives": [ + { + "index": "a", + "ranges": ["1 <= a <= 1"], + "rowid_ordered": true, + "using_mrr": false, + "index_only": true, + "rows": 1, + "cost": 2.21, + "chosen": true + } + ], + "index_to_merge": "a", + "cumulated_cost": 2.21 + }, + { + "range_scan_alternatives": [ + { + "index": "b", + "ranges": ["1 <= b <= 1"], + "rowid_ordered": true, + "using_mrr": false, + "index_only": true, + "rows": 1, + "cost": 2.21, + "chosen": true + } + ], + "index_to_merge": "b", + "cumulated_cost": 4.42 + } + ], + "cost_of_reading_ranges": 4.42, + "use_roworder_union": true, + "cause": "always cheaper than non roworder retrieval", + "analyzing_roworder_scans": [ + { + "type": "range_scan", + "index": "a", + "rows": 1, + "ranges": ["1 <= a <= 1"], + "analyzing_roworder_intersect": { + "cause": "too few roworder scans" + } + }, + { + "type": "range_scan", + "index": "b", + "rows": 1, + "ranges": ["1 <= b <= 1"], + "analyzing_roworder_intersect": { + "cause": "too few roworder scans" + } + } + ], + "index_roworder_union_cost": 6.2137, + "members": 2, + "chosen": true + } + ] + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "index_roworder_union", + "union_of": [ + { + "type": "range_scan", + "index": "a", + "rows": 1, + "ranges": ["1 <= a <= 1"] + }, + { + "type": "range_scan", + "index": "b", + "rows": 1, + "ranges": ["1 <= b <= 1"] + } + ] + }, + "rows_for_plan": 2, + "cost_for_plan": 6.2137, + "chosen": true + } + } + }, + { + "selectivity_for_indexes": [], + "selectivity_for_columns": [] + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "range", + "resulting_rows": 2, + "cost": 6.2137, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t1.a = 1 or t1.b = 1", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": "t1.a = 1 or t1.b = 1" + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +drop table t0,t1; +set optimizer_trace="enabled=off"; +set @@optimizer_switch= @tmp_opt_switch; diff --git a/mysql-test/main/opt_trace_index_merge.test b/mysql-test/main/opt_trace_index_merge.test new file mode 100644 index 00000000000..d5efaf81db5 --- /dev/null +++ b/mysql-test/main/opt_trace_index_merge.test @@ -0,0 +1,21 @@ +--source include/not_embedded.inc +set @tmp_opt_switch= @@optimizer_switch; +set optimizer_switch='index_merge_sort_intersection=on'; +set optimizer_trace='enabled=on'; +create table t0 (a int); +insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t1 (a int, b int, c int, filler char(100), + key(a), key(b), key(c)); +insert into t1 select + A.a * B.a*10 + C.a*100, + A.a * B.a*10 + C.a*100, + A.a, + 'filler' +from t0 A, t0 B, t0 C; + +--echo This should use union: +explain select * from t1 where a=1 or b=1; +select * from information_schema.OPTIMIZER_TRACE; +drop table t0,t1; +set optimizer_trace="enabled=off"; +set @@optimizer_switch= @tmp_opt_switch; diff --git a/mysql-test/main/opt_trace_index_merge_innodb.result b/mysql-test/main/opt_trace_index_merge_innodb.result new file mode 100644 index 00000000000..a0f03e326a3 --- /dev/null +++ b/mysql-test/main/opt_trace_index_merge_innodb.result @@ -0,0 +1,242 @@ +create table t1 +( +pk1 int not null, +pk2 int not null, +key1 int not null, +key2 int not null, +key (key1), +key (key2), +primary key (pk1, pk2) +)engine=Innodb; +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze status OK +set optimizer_trace="enabled=on"; +set @tmp_index_merge_ror_cpk=@@optimizer_switch; +set optimizer_switch='extended_keys=off'; +explain select * from t1 where pk1 != 0 and key1 = 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref PRIMARY,key1 key1 4 const 1 Using index condition +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +explain select * from t1 where pk1 != 0 and key1 = 1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `t1`.`pk1` AS `pk1`,`t1`.`pk2` AS `pk2`,`t1`.`key1` AS `key1`,`t1`.`key2` AS `key2` from `t1` where `t1`.`pk1` <> 0 and `t1`.`key1` = 1" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "condition_processing": { + "condition": "WHERE", + "original_condition": "t1.pk1 <> 0 and t1.key1 = 1", + "steps": [ + { + "transformation": "equality_propagation", + "resulting_condition": "t1.pk1 <> 0 and multiple equal(1, t1.key1)" + }, + { + "transformation": "constant_propagation", + "resulting_condition": "t1.pk1 <> 0 and multiple equal(1, t1.key1)" + }, + { + "transformation": "trivial_condition_removal", + "resulting_condition": "t1.pk1 <> 0 and multiple equal(1, t1.key1)" + } + ] + } + }, + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "ref_optimizer_key_uses": [ + { + "table": "t1", + "field": "key1", + "equals": "1", + "null_rejecting": false + } + ] + }, + { + "rows_estimation": [ + { + "table": "t1", + "range_analysis": { + "table_scan": { + "rows": 1000, + "cost": 206.1 + }, + "potential_range_indexes": [ + { + "index": "PRIMARY", + "usable": true, + "key_parts": ["pk1", "pk2"] + }, + { + "index": "key1", + "usable": true, + "key_parts": ["key1"] + }, + { + "index": "key2", + "usable": false, + "cause": "not applicable" + } + ], + "setup_range_conditions": [], + "group_index_range": { + "chosen": false, + "cause": "no group by or distinct" + }, + "analyzing_range_alternatives": { + "range_scan_alternatives": [ + { + "index": "PRIMARY", + "ranges": ["pk1 < 0", "0 < pk1"], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 1001, + "cost": 203.59, + "chosen": true + }, + { + "index": "key1", + "ranges": ["1 <= key1 <= 1"], + "rowid_ordered": true, + "using_mrr": false, + "index_only": false, + "rows": 1, + "cost": 2.21, + "chosen": true + } + ], + "analyzing_roworder_intersect": { + "intersecting_indexes": [ + { + "index": "key1", + "index_scan_cost": 1, + "cumulateed_index_scan_cost": 1, + "disk_sweep_cost": 1.0014, + "cumulative_total_cost": 2.0014, + "usable": true, + "matching_rows_now": 1, + "intersect_covering_with_this_index": false, + "chosen": true + } + ], + "clustered_pk": { + "index_scan_cost": 0.002, + "cumulateed_index_scan_cost": 1.002, + "disk_sweep_cost": 1.0014, + "clustered_pk_added_to_intersect": false, + "cause": "cost" + }, + "chosen": false, + "cause": "too few indexes to merge" + }, + "analyzing_index_merge_union": [] + }, + "chosen_range_access_summary": { + "range_access_plan": { + "type": "range_scan", + "index": "key1", + "rows": 1, + "ranges": ["1 <= key1 <= 1"] + }, + "rows_for_plan": 1, + "cost_for_plan": 2.21, + "chosen": true + } + } + }, + { + "selectivity_for_indexes": [ + { + "index_name": "PRIMARY", + "selectivity_from_index": 1.001 + }, + { + "index_name": "key1", + "selectivity_from_index": 0.001 + } + ], + "selectivity_for_columns": [] + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "ref", + "index": "key1", + "used_range_estimates": true, + "rows": 1, + "cost": 2, + "chosen": true + }, + { + "type": "scan", + "chosen": false, + "cause": "cost" + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": "t1.key1 = 1 and t1.pk1 <> 0", + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": "t1.pk1 <> 0" + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +drop table t1; +set @@optimizer_switch= @tmp_index_merge_ror_cpk; +set optimizer_trace="enabled=off"; diff --git a/mysql-test/main/opt_trace_index_merge_innodb.test b/mysql-test/main/opt_trace_index_merge_innodb.test new file mode 100644 index 00000000000..5e18185bf7f --- /dev/null +++ b/mysql-test/main/opt_trace_index_merge_innodb.test @@ -0,0 +1,31 @@ +--source include/not_embedded.inc +--source include/have_innodb.inc +create table t1 +( + pk1 int not null, + pk2 int not null, + key1 int not null, + key2 int not null, + key (key1), + key (key2), + primary key (pk1, pk2) +)engine=Innodb; + +--disable_query_log +let $1=1000; +while ($1) +{ + eval insert into t1 values (1+$1/10,$1 mod 100,$1,$1/100); + dec $1; +} +--enable_query_log +analyze table t1; + +set optimizer_trace="enabled=on"; +set @tmp_index_merge_ror_cpk=@@optimizer_switch; +set optimizer_switch='extended_keys=off'; +explain select * from t1 where pk1 != 0 and key1 = 1; +select * from information_schema.OPTIMIZER_TRACE; +drop table t1; +set @@optimizer_switch= @tmp_index_merge_ror_cpk; +set optimizer_trace="enabled=off"; diff --git a/mysql-test/main/opt_trace_security.result b/mysql-test/main/opt_trace_security.result new file mode 100644 index 00000000000..2d66a0a9576 --- /dev/null +++ b/mysql-test/main/opt_trace_security.result @@ -0,0 +1,396 @@ +create database db1; +use db1; +create table t1(a int); +insert into t1 values (1),(2),(3); +create table t2(a int); +CREATE USER 'foo'@'%'; +CREATE USER 'bar'@'%'; +create definer=foo SQL SECURITY definer view db1.v1 as select * from db1.t1; +create definer=foo function f1 (a int) returns INT SQL SECURITY DEFINER +BEGIN +insert into t2 select * from t1; +return a+1; +END| +set optimizer_trace="enabled=on"; +select * from db1.t1; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1' +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES + 0 1 +set optimizer_trace="enabled=off"; +grant select(a) on db1.t1 to 'foo'@'%'; +set optimizer_trace="enabled=on"; +select * from db1.t1; +a +1 +2 +3 +# INSUFFICIENT PRIVILEGES should be set to 1 +# Trace and Query should be empty +# We need SELECT privilege on the table db1.t1; +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES + 0 1 +set optimizer_trace="enabled=off"; +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +grant select on db1.t1 to 'foo'@'%'; +grant select on db1.t2 to 'foo'@'%'; +set optimizer_trace="enabled=on"; +# +# SELECT privilege on the table db1.t1 +# The trace would be present. +# +select * from db1.t1; +a +1 +2 +3 +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +select * from db1.t1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "expanded_query": "select `db1`.`t1`.`a` AS `a` from `t1`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "rows_estimation": [ + { + "table": "t1", + "table_scan": { + "rows": 3, + "cost": 2.0051 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 3, + "cost": 2.0051, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": null, + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +set optimizer_trace="enabled=off"; +grant select on db1.v1 to 'foo'@'%'; +grant show view on db1.v1 to 'foo'@'%'; +grant select on db1.v1 to 'bar'@'%'; +grant show view on db1.v1 to 'bar'@'%'; +select current_user(); +current_user() +foo@% +set optimizer_trace="enabled=on"; +select * from db1.v1; +a +1 +2 +3 +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES +select * from db1.v1 { + "steps": [ + { + "join_preparation": { + "select_id": 1, + "steps": [ + { + "view": { + "table": "v1", + "select_id": 2, + "merged": true + } + }, + { + "join_preparation": { + "select_id": 2, + "steps": [ + { + "expanded_query": "/* select#2 */ select `db1`.`t1`.`a` AS `a` from `t1`" + } + ] + } + }, + { + "expanded_query": "/* select#1 */ select `db1`.`t1`.`a` AS `a` from `v1`" + } + ] + } + }, + { + "join_optimization": { + "select_id": 1, + "steps": [ + { + "table_dependencies": [ + { + "table": "t1", + "row_may_be_null": false, + "map_bit": 0, + "depends_on_map_bits": [] + } + ] + }, + { + "rows_estimation": [ + { + "table": "t1", + "table_scan": { + "rows": 3, + "cost": 2.0051 + } + } + ] + }, + { + "execution_plan_for_potential_materialization": { + "steps": [] + } + }, + { + "considered_execution_plans": [ + { + "plan_prefix": [], + "table": "t1", + "best_access_path": { + "considered_access_paths": [ + { + "access_type": "scan", + "resulting_rows": 3, + "cost": 2.0051, + "chosen": true + } + ] + } + } + ] + }, + { + "attaching_conditions_to_tables": { + "original_condition": null, + "attached_conditions_computation": [], + "attached_conditions_summary": [ + { + "table": "t1", + "attached": null + } + ] + } + } + ] + } + }, + { + "join_execution": { + "select_id": 1, + "steps": [] + } + } + ] +} 0 0 +set optimizer_trace="enabled=off"; +select current_user(); +current_user() +bar@% +set optimizer_trace="enabled=on"; +select * from db1.v1; +a +1 +2 +3 +# +# INSUFFICIENT PRIVILEGES should be set to 1 +# Trace and Query should be empty +# Privileges for the underlying tables of the +# view should also be present for the current user +# +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES + 0 1 +set optimizer_trace="enabled=off"; +grant execute on function db1.f1 to 'foo'@'%'; +grant execute on function db1.f1 to 'bar'@'%'; +grant select on db1.t1 to 'bar'@'%'; +grant insert on db1.t2 to 'foo'@'%'; +select current_user(); +current_user() +foo@% +set optimizer_trace="enabled=on"; +select db1.f1(a) from db1.t1; +db1.f1(a) +2 +3 +4 +select INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE; +INSUFFICIENT_PRIVILEGES +0 +set optimizer_trace="enabled=off"; +select current_user(); +current_user() +bar@% +set optimizer_trace="enabled=on"; +# +# The trace should be empty, because the current user +# does not have INSERT privilege for table t2 which is +# used in the function f1 +# +select db1.f1(a) from db1.t1; +db1.f1(a) +2 +3 +4 +select * from information_schema.OPTIMIZER_TRACE; +QUERY TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE INSUFFICIENT_PRIVILEGES + 0 1 +set optimizer_trace="enabled=off"; +select current_user(); +current_user() +root@localhost +REVOKE ALL PRIVILEGES, GRANT OPTION FROM foo; +drop user if exists foo; +drop user if exists bar; +drop table db1.t1, db1.t2; +drop database db1; +# +# Privilege checking for optimizer trace across connections +# +connection default; +create database db1; +use db1; +create table t1(a int); +insert into t1 values (1),(2),(3); +create table t2(a int); +CREATE USER 'foo'@'localhost'; +CREATE USER 'bar'@'localhost'; +grant all on *.* to foo@localhost with grant option; +grant all on *.* to bar@localhost with grant option; +connect con_foo,localhost, foo,, db1; +connection default; +connect con_bar,localhost, bar,, db1; +connection default; +create definer=foo@localhost SQL SECURITY definer view db1.v1 as select * from db1.t1; +create function f1 (a int) returns INT SQL SECURITY DEFINER +BEGIN +insert into t2 select * from t1; +return a+1; +END| +grant execute on function f1 to bar@localhost; +connection con_foo; +set optimizer_trace='enabled=on'; +select * from db1.t1; +a +1 +2 +3 +# +# Test that security context changes are allowed when, and only +# when, invoker has all global privileges. +# +select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE; +query INSUFFICIENT_PRIVILEGES +select * from db1.t1 0 +set optimizer_trace='enabled=off'; +connection con_bar; +set optimizer_trace='enabled=on'; +select f1(a) from db1.t1; +f1(a) +2 +3 +4 +select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE; +query INSUFFICIENT_PRIVILEGES +select f1(a) from db1.t1 0 +set optimizer_trace='enabled=off'; +connection default; +revoke shutdown on *.* from foo@localhost; +disconnect con_foo; +connect con_foo, localhost, foo,, db1; +connection con_foo; +set optimizer_trace='enabled=on'; +select f1(a) from db1.t1; +f1(a) +2 +3 +4 +# +# Test to check if invoker has all global privileges or not, only then +# the security context changes are allowed. The user has been revoked +# shutdown privilege so INSUFFICIENT PRIVILEGES should be set to 1. +# +select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE; +query INSUFFICIENT_PRIVILEGES + 1 +set optimizer_trace='enabled=off'; +connection default; +select current_user(); +current_user() +root@localhost +select * from db1.v1; +a +1 +2 +3 +drop user foo@localhost, bar@localhost; +drop view db1.v1; +drop table db1.t1; +drop database db1; +set optimizer_trace="enabled=off"; diff --git a/mysql-test/main/opt_trace_security.test b/mysql-test/main/opt_trace_security.test new file mode 100644 index 00000000000..9fa49190990 --- /dev/null +++ b/mysql-test/main/opt_trace_security.test @@ -0,0 +1,197 @@ +--source include/not_embedded.inc +create database db1; +use db1; +create table t1(a int); +insert into t1 values (1),(2),(3); +create table t2(a int); + +CREATE USER 'foo'@'%'; +CREATE USER 'bar'@'%'; + +create definer=foo SQL SECURITY definer view db1.v1 as select * from db1.t1; + +delimiter |; +create definer=foo function f1 (a int) returns INT SQL SECURITY DEFINER +BEGIN + insert into t2 select * from t1; + return a+1; +END| +delimiter ;| + +--change_user foo +set optimizer_trace="enabled=on"; +--error 1142 +select * from db1.t1; +select * from information_schema.OPTIMIZER_TRACE; +set optimizer_trace="enabled=off"; + +--change_user root +grant select(a) on db1.t1 to 'foo'@'%'; + +--change_user foo +set optimizer_trace="enabled=on"; +select * from db1.t1; + +--echo # INSUFFICIENT PRIVILEGES should be set to 1 +--echo # Trace and Query should be empty +--echo # We need SELECT privilege on the table db1.t1; + +select * from information_schema.OPTIMIZER_TRACE; +set optimizer_trace="enabled=off"; + +--change_user root +select * from information_schema.OPTIMIZER_TRACE; +grant select on db1.t1 to 'foo'@'%'; +grant select on db1.t2 to 'foo'@'%'; + +--change_user foo +set optimizer_trace="enabled=on"; + +--echo # +--echo # SELECT privilege on the table db1.t1 +--echo # The trace would be present. +--echo # +select * from db1.t1; +select * from information_schema.OPTIMIZER_TRACE; +set optimizer_trace="enabled=off"; + +--change_user root + +grant select on db1.v1 to 'foo'@'%'; +grant show view on db1.v1 to 'foo'@'%'; + +grant select on db1.v1 to 'bar'@'%'; +grant show view on db1.v1 to 'bar'@'%'; + +--change_user foo +select current_user(); +set optimizer_trace="enabled=on"; +select * from db1.v1; +select * from information_schema.OPTIMIZER_TRACE; +set optimizer_trace="enabled=off"; + +--change_user bar +select current_user(); +set optimizer_trace="enabled=on"; +select * from db1.v1; +--echo # +--echo # INSUFFICIENT PRIVILEGES should be set to 1 +--echo # Trace and Query should be empty +--echo # Privileges for the underlying tables of the +--echo # view should also be present for the current user +--echo # +select * from information_schema.OPTIMIZER_TRACE; +set optimizer_trace="enabled=off"; + +--change_user root +grant execute on function db1.f1 to 'foo'@'%'; +grant execute on function db1.f1 to 'bar'@'%'; + +grant select on db1.t1 to 'bar'@'%'; +grant insert on db1.t2 to 'foo'@'%'; + +--change_user foo +select current_user(); +set optimizer_trace="enabled=on"; + +select db1.f1(a) from db1.t1; +select INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE; +set optimizer_trace="enabled=off"; + +--change_user bar +select current_user(); +set optimizer_trace="enabled=on"; +--echo # +--echo # The trace should be empty, because the current user +--echo # does not have INSERT privilege for table t2 which is +--echo # used in the function f1 +--echo # +select db1.f1(a) from db1.t1; +select * from information_schema.OPTIMIZER_TRACE; +set optimizer_trace="enabled=off"; + +--change_user root +select current_user(); +REVOKE ALL PRIVILEGES, GRANT OPTION FROM foo; + +--change_user root +drop user if exists foo; +drop user if exists bar; +drop table db1.t1, db1.t2; +drop database db1; + + +--echo # +--echo # Privilege checking for optimizer trace across connections +--echo # + +connection default; +create database db1; +use db1; +create table t1(a int); +insert into t1 values (1),(2),(3); +create table t2(a int); + +CREATE USER 'foo'@'localhost'; +CREATE USER 'bar'@'localhost'; +grant all on *.* to foo@localhost with grant option; +grant all on *.* to bar@localhost with grant option; +#grant select on db1.t1 to bar@localhost; +#grant insert on db1.t2 to bar@localhost; + +connect (con_foo,localhost, foo,, db1); +connection default; +connect (con_bar,localhost, bar,, db1); +connection default; +create definer=foo@localhost SQL SECURITY definer view db1.v1 as select * from db1.t1; + +delimiter |; +create function f1 (a int) returns INT SQL SECURITY DEFINER +BEGIN + insert into t2 select * from t1; + return a+1; +END| +delimiter ;| + +grant execute on function f1 to bar@localhost; + +connection con_foo; +set optimizer_trace='enabled=on'; +select * from db1.t1; +--echo # +--echo # Test that security context changes are allowed when, and only +--echo # when, invoker has all global privileges. +--echo # +select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE; +set optimizer_trace='enabled=off'; + +connection con_bar; +set optimizer_trace='enabled=on'; +select f1(a) from db1.t1; +select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE; +set optimizer_trace='enabled=off'; + +connection default; +revoke shutdown on *.* from foo@localhost; +disconnect con_foo; +connect (con_foo, localhost, foo,, db1); + +connection con_foo; +set optimizer_trace='enabled=on'; +select f1(a) from db1.t1; +--echo # +--echo # Test to check if invoker has all global privileges or not, only then +--echo # the security context changes are allowed. The user has been revoked +--echo # shutdown privilege so INSUFFICIENT PRIVILEGES should be set to 1. +--echo # +select query, INSUFFICIENT_PRIVILEGES from information_schema.OPTIMIZER_TRACE; +set optimizer_trace='enabled=off'; + +connection default; +select current_user(); +select * from db1.v1; +drop user foo@localhost, bar@localhost; +drop view db1.v1; +drop table db1.t1; +drop database db1; +set optimizer_trace="enabled=off"; diff --git a/mysql-test/suite/funcs_1/r/is_columns_is.result b/mysql-test/suite/funcs_1/r/is_columns_is.result index dfaa5d75137..386b0f07f98 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is.result @@ -205,6 +205,10 @@ def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA 10 NULL YES varc def information_schema KEY_COLUMN_USAGE TABLE_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select NEVER NULL def information_schema KEY_COLUMN_USAGE TABLE_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL def information_schema KEY_COLUMN_USAGE TABLE_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL +def information_schema OPTIMIZER_TRACE INSUFFICIENT_PRIVILEGES 4 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) select NEVER NULL +def information_schema OPTIMIZER_TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(20) select NEVER NULL +def information_schema OPTIMIZER_TRACE QUERY 1 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL +def information_schema OPTIMIZER_TRACE TRACE 2 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext select NEVER NULL def information_schema PARAMETERS CHARACTER_MAXIMUM_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL def information_schema PARAMETERS CHARACTER_OCTET_LENGTH 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) select NEVER NULL def information_schema PARAMETERS CHARACTER_SET_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NEVER NULL @@ -743,6 +747,10 @@ NULL information_schema KEY_COLUMN_USAGE POSITION_IN_UNIQUE_CONSTRAINT bigint NU 3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_COLUMN_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) +1.0000 information_schema OPTIMIZER_TRACE QUERY longtext 4294967295 4294967295 utf8 utf8_general_ci longtext +1.0000 information_schema OPTIMIZER_TRACE TRACE longtext 4294967295 4294967295 utf8 utf8_general_ci longtext +NULL information_schema OPTIMIZER_TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE int NULL NULL NULL NULL int(20) +NULL information_schema OPTIMIZER_TRACE INSUFFICIENT_PRIVILEGES tinyint NULL NULL NULL NULL tinyint(1) 3.0000 information_schema PARAMETERS SPECIFIC_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512) 3.0000 information_schema PARAMETERS SPECIFIC_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema PARAMETERS SPECIFIC_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) diff --git a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result index 96fb1e286c0..97346c4648d 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is_embedded.result @@ -205,6 +205,10 @@ def information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA 10 NULL YES varc def information_schema KEY_COLUMN_USAGE TABLE_CATALOG 4 '' NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) NEVER NULL def information_schema KEY_COLUMN_USAGE TABLE_NAME 6 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL def information_schema KEY_COLUMN_USAGE TABLE_SCHEMA 5 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL +def information_schema OPTIMIZER_TRACE INSUFFICIENT_PRIVILEGES 4 0 NO tinyint NULL NULL 3 0 NULL NULL NULL tinyint(1) NEVER NULL +def information_schema OPTIMIZER_TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE 3 0 NO int NULL NULL 10 0 NULL NULL NULL int(20) NEVER NULL +def information_schema OPTIMIZER_TRACE QUERY 1 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL +def information_schema OPTIMIZER_TRACE TRACE 2 '' NO longtext 4294967295 4294967295 NULL NULL NULL utf8 utf8_general_ci longtext NEVER NULL def information_schema PARAMETERS CHARACTER_MAXIMUM_LENGTH 8 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL def information_schema PARAMETERS CHARACTER_OCTET_LENGTH 9 NULL YES int NULL NULL 10 0 NULL NULL NULL int(21) NEVER NULL def information_schema PARAMETERS CHARACTER_SET_NAME 13 NULL YES varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) NEVER NULL @@ -743,6 +747,10 @@ NULL information_schema KEY_COLUMN_USAGE POSITION_IN_UNIQUE_CONSTRAINT bigint NU 3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema KEY_COLUMN_USAGE REFERENCED_COLUMN_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) +1.0000 information_schema OPTIMIZER_TRACE QUERY longtext 4294967295 4294967295 utf8 utf8_general_ci longtext +1.0000 information_schema OPTIMIZER_TRACE TRACE longtext 4294967295 4294967295 utf8 utf8_general_ci longtext +NULL information_schema OPTIMIZER_TRACE MISSING_BYTES_BEYOND_MAX_MEM_SIZE int NULL NULL NULL NULL int(20) +NULL information_schema OPTIMIZER_TRACE INSUFFICIENT_PRIVILEGES tinyint NULL NULL NULL NULL tinyint(1) 3.0000 information_schema PARAMETERS SPECIFIC_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512) 3.0000 information_schema PARAMETERS SPECIFIC_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema PARAMETERS SPECIFIC_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) diff --git a/mysql-test/suite/funcs_1/r/is_tables_is.result b/mysql-test/suite/funcs_1/r/is_tables_is.result index 5fee1e0050a..9af3aa860a0 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_is.result +++ b/mysql-test/suite/funcs_1/r/is_tables_is.result @@ -489,6 +489,31 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME OPTIMIZER_TRACE +TABLE_TYPE SYSTEM VIEW +ENGINE MYISAM_OR_MARIA +VERSION 11 +ROW_FORMAT DYNAMIC_OR_PAGE +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_general_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +MAX_INDEX_LENGTH #MIL# +TEMPORARY Y +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME PARAMETERS TABLE_TYPE SYSTEM VIEW ENGINE MYISAM_OR_MARIA @@ -1530,6 +1555,31 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME OPTIMIZER_TRACE +TABLE_TYPE SYSTEM VIEW +ENGINE MYISAM_OR_MARIA +VERSION 11 +ROW_FORMAT DYNAMIC_OR_PAGE +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_general_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +MAX_INDEX_LENGTH #MIL# +TEMPORARY Y +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME PARAMETERS TABLE_TYPE SYSTEM VIEW ENGINE MYISAM_OR_MARIA diff --git a/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result b/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result index 5fee1e0050a..9af3aa860a0 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result +++ b/mysql-test/suite/funcs_1/r/is_tables_is_embedded.result @@ -489,6 +489,31 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME OPTIMIZER_TRACE +TABLE_TYPE SYSTEM VIEW +ENGINE MYISAM_OR_MARIA +VERSION 11 +ROW_FORMAT DYNAMIC_OR_PAGE +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_general_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +MAX_INDEX_LENGTH #MIL# +TEMPORARY Y +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME PARAMETERS TABLE_TYPE SYSTEM VIEW ENGINE MYISAM_OR_MARIA @@ -1530,6 +1555,31 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME OPTIMIZER_TRACE +TABLE_TYPE SYSTEM VIEW +ENGINE MYISAM_OR_MARIA +VERSION 11 +ROW_FORMAT DYNAMIC_OR_PAGE +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT NULL +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION utf8_general_ci +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +MAX_INDEX_LENGTH #MIL# +TEMPORARY Y +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME PARAMETERS TABLE_TYPE SYSTEM VIEW ENGINE MYISAM_OR_MARIA diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff index 5d47090a875..4ec990dbd6a 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded,32bit.rdiff @@ -1,6 +1,6 @@ ---- sysvars_server_embedded.result 2017-11-17 17:00:22.462630239 +0100 -+++ sysvars_server_embedded,32bit.reject 2017-11-17 19:09:55.472258411 +0100 -@@ -58,7 +58,7 @@ +--- suite/sys_vars/r/sysvars_server_embedded.result 2019-02-09 22:10:13.570328367 +0530 ++++ suite/sys_vars/r/sysvars_server_embedded,32bit.reject 2019-02-09 22:35:54.884594853 +0530 +@@ -74,7 +74,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -9,7 +9,7 @@ VARIABLE_COMMENT Auto-increment columns are incremented by this NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 65535 -@@ -72,7 +72,7 @@ +@@ -88,7 +88,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -18,7 +18,7 @@ VARIABLE_COMMENT Offset added to Auto-increment columns. Used when auto-increment-increment != 1 NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 65535 -@@ -86,7 +86,7 @@ +@@ -102,7 +102,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 150 VARIABLE_SCOPE GLOBAL @@ -27,7 +27,7 @@ VARIABLE_COMMENT The number of outstanding connection requests MariaDB can have. This comes into play when the main MariaDB thread gets very many connection requests in a very short time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -159,7 +159,7 @@ +@@ -175,7 +175,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the transactional cache for updates to transactional engines for the binary log. If you often use transactions containing many statements, you can increase this to get more performance NUMERIC_MIN_VALUE 4096 @@ -36,7 +36,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -184,10 +184,10 @@ +@@ -200,10 +200,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -49,7 +49,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -198,10 +198,10 @@ +@@ -214,10 +214,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100000 VARIABLE_SCOPE GLOBAL @@ -62,7 +62,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -229,7 +229,7 @@ +@@ -245,7 +245,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of file cache for the binary log NUMERIC_MIN_VALUE 8192 @@ -71,7 +71,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -285,7 +285,7 @@ +@@ -301,7 +301,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the statement cache for updates to non-transactional engines for the binary log. If you often use statements updating a great number of rows, you can increase this to get more performance. NUMERIC_MIN_VALUE 4096 @@ -80,7 +80,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -299,7 +299,7 @@ +@@ -315,7 +315,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread! NUMERIC_MIN_VALUE 0 @@ -89,7 +89,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -562,7 +562,7 @@ +@@ -578,7 +578,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -98,7 +98,7 @@ VARIABLE_COMMENT The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake' NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 31536000 -@@ -618,7 +618,7 @@ +@@ -648,7 +648,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 15 VARIABLE_SCOPE SESSION @@ -107,7 +107,7 @@ VARIABLE_COMMENT Long search depth for the two-step deadlock detection NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 33 -@@ -632,7 +632,7 @@ +@@ -662,7 +662,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4 VARIABLE_SCOPE SESSION @@ -116,7 +116,7 @@ VARIABLE_COMMENT Short search depth for the two-step deadlock detection NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 32 -@@ -646,7 +646,7 @@ +@@ -676,7 +676,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50000000 VARIABLE_SCOPE SESSION @@ -125,7 +125,7 @@ VARIABLE_COMMENT Long timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -660,7 +660,7 @@ +@@ -690,7 +690,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10000 VARIABLE_SCOPE SESSION @@ -134,7 +134,7 @@ VARIABLE_COMMENT Short timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -716,7 +716,7 @@ +@@ -746,7 +746,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -143,7 +143,7 @@ VARIABLE_COMMENT The default week format used by WEEK() functions NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 7 -@@ -730,7 +730,7 @@ +@@ -760,7 +760,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -152,7 +152,7 @@ VARIABLE_COMMENT After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -744,7 +744,7 @@ +@@ -774,7 +774,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 300 VARIABLE_SCOPE GLOBAL @@ -161,7 +161,7 @@ VARIABLE_COMMENT How long a INSERT DELAYED thread should wait for INSERT statements before terminating NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -758,7 +758,7 @@ +@@ -788,7 +788,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1000 VARIABLE_SCOPE GLOBAL @@ -170,7 +170,7 @@ VARIABLE_COMMENT What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -786,7 +786,7 @@ +@@ -816,7 +816,7 @@ GLOBAL_VALUE_ORIGIN SQL DEFAULT_VALUE 4 VARIABLE_SCOPE SESSION @@ -179,7 +179,7 @@ VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 38 -@@ -884,7 +884,7 @@ +@@ -928,7 +928,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -188,7 +188,7 @@ VARIABLE_COMMENT If non-zero, binary logs will be purged after expire_logs_days days; possible purges happen at startup and at binary log rotation NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 99 -@@ -926,7 +926,7 @@ +@@ -970,7 +970,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE GLOBAL @@ -197,7 +197,7 @@ VARIABLE_COMMENT The number of connections on extra-port NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100000 -@@ -968,7 +968,7 @@ +@@ -1012,7 +1012,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -206,7 +206,7 @@ VARIABLE_COMMENT A dedicated thread is created to flush all tables at the given interval NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -1010,7 +1010,7 @@ +@@ -1054,7 +1054,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 84 VARIABLE_SCOPE GLOBAL @@ -215,7 +215,7 @@ VARIABLE_COMMENT The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 84 -@@ -1024,7 +1024,7 @@ +@@ -1068,7 +1068,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4 VARIABLE_SCOPE GLOBAL @@ -224,7 +224,7 @@ VARIABLE_COMMENT The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 84 -@@ -1038,7 +1038,7 @@ +@@ -1082,7 +1082,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 20 VARIABLE_SCOPE GLOBAL @@ -233,7 +233,7 @@ VARIABLE_COMMENT Number of best matches to use for query expansion NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000 -@@ -1097,7 +1097,7 @@ +@@ -1141,7 +1141,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The maximum length of the result of function GROUP_CONCAT() NUMERIC_MIN_VALUE 4 @@ -242,7 +242,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1248,7 +1248,7 @@ +@@ -1292,7 +1292,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -251,7 +251,7 @@ VARIABLE_COMMENT Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -1276,7 +1276,7 @@ +@@ -1320,7 +1320,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 128 VARIABLE_SCOPE GLOBAL @@ -260,7 +260,7 @@ VARIABLE_COMMENT How many host names should be cached to avoid resolving. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65536 -@@ -1430,7 +1430,7 @@ +@@ -1474,7 +1474,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 28800 VARIABLE_SCOPE SESSION @@ -269,20 +269,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on an interactive connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1444,10 +1444,10 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 1000 - VARIABLE_SCOPE SESSION --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT The minimum number of scalar elements in the value list of IN predicate that triggers its conversion to IN subquery - NUMERIC_MIN_VALUE 0 --NUMERIC_MAX_VALUE 18446744073709551615 -+NUMERIC_MAX_VALUE 4294967295 - NUMERIC_BLOCK_SIZE 1 - ENUM_VALUE_LIST NULL - READ_ONLY NO -@@ -1475,7 +1475,7 @@ +@@ -1505,7 +1505,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer that is used for joins NUMERIC_MIN_VALUE 128 @@ -291,7 +278,7 @@ NUMERIC_BLOCK_SIZE 128 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1500,7 +1500,7 @@ +@@ -1530,7 +1530,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE SESSION @@ -300,7 +287,7 @@ VARIABLE_COMMENT Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers while even numbers are used for linked buffers NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 8 -@@ -1531,7 +1531,7 @@ +@@ -1561,7 +1561,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford NUMERIC_MIN_VALUE 0 @@ -309,7 +296,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1738,7 +1738,7 @@ +@@ -1768,7 +1768,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 86400 VARIABLE_SCOPE SESSION @@ -318,7 +305,7 @@ VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -1906,7 +1906,7 @@ +@@ -1936,7 +1936,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -327,7 +314,7 @@ VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -1948,7 +1948,7 @@ +@@ -1978,7 +1978,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE SESSION @@ -336,7 +323,7 @@ VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -1990,7 +1990,7 @@ +@@ -2020,7 +2020,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16777216 VARIABLE_SCOPE SESSION @@ -345,7 +332,7 @@ VARIABLE_COMMENT Max packet length to send to or receive from the server NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -2000,14 +2000,14 @@ +@@ -2030,14 +2030,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_BINLOG_CACHE_SIZE SESSION_VALUE NULL @@ -363,7 +350,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2018,7 +2018,7 @@ +@@ -2048,7 +2048,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL @@ -372,7 +359,7 @@ VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 1073741824 -@@ -2028,14 +2028,14 @@ +@@ -2058,14 +2058,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_BINLOG_STMT_CACHE_SIZE SESSION_VALUE NULL @@ -390,16 +377,16 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2046,7 +2046,7 @@ +@@ -2076,7 +2076,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 151 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of simultaneous clients allowed - NUMERIC_MIN_VALUE 1 + NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 100000 -@@ -2060,7 +2060,7 @@ +@@ -2090,7 +2090,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -408,7 +395,7 @@ VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2074,7 +2074,7 @@ +@@ -2104,7 +2104,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 20 VARIABLE_SCOPE SESSION @@ -417,7 +404,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -2102,7 +2102,7 @@ +@@ -2132,7 +2132,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 64 VARIABLE_SCOPE SESSION @@ -426,7 +413,7 @@ VARIABLE_COMMENT Max number of errors/warnings to store for a statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -2119,7 +2119,7 @@ +@@ -2149,7 +2149,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't allow creation of heap tables bigger than this NUMERIC_MIN_VALUE 16384 @@ -435,7 +422,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2130,7 +2130,7 @@ +@@ -2160,7 +2160,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 20 VARIABLE_SCOPE SESSION @@ -444,7 +431,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -2158,7 +2158,7 @@ +@@ -2188,7 +2188,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE SESSION @@ -453,7 +440,7 @@ VARIABLE_COMMENT Max number of bytes in sorted records NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -2172,7 +2172,7 @@ +@@ -2202,7 +2202,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -462,16 +449,7 @@ VARIABLE_COMMENT The maximum BLOB length to send to server from mysql_send_long_data API. Deprecated option; use max_allowed_packet instead. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2186,7 +2186,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 16382 - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Maximum number of prepared statements in the server - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 1048576 -@@ -2200,7 +2200,7 @@ +@@ -2244,7 +2244,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE SESSION @@ -480,7 +458,7 @@ VARIABLE_COMMENT Maximum number of iterations when executing recursive queries NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2214,7 +2214,7 @@ +@@ -2258,7 +2258,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE SESSION @@ -489,7 +467,7 @@ VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2242,7 +2242,7 @@ +@@ -2286,7 +2286,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE SESSION @@ -498,7 +476,7 @@ VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -2256,7 +2256,7 @@ +@@ -2300,7 +2300,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -507,7 +485,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -2284,7 +2284,7 @@ +@@ -2328,7 +2328,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32 VARIABLE_SCOPE SESSION @@ -516,7 +494,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2312,7 +2312,7 @@ +@@ -2356,7 +2356,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE GLOBAL @@ -525,7 +503,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2326,7 +2326,7 @@ +@@ -2370,7 +2370,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -534,7 +512,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -2340,7 +2340,7 @@ +@@ -2384,7 +2384,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8 VARIABLE_SCOPE GLOBAL @@ -543,7 +521,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2354,7 +2354,7 @@ +@@ -2398,7 +2398,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -552,7 +530,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2368,7 +2368,7 @@ +@@ -2412,7 +2412,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -561,7 +539,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2382,10 +2382,10 @@ +@@ -2426,10 +2426,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE SESSION @@ -574,7 +552,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2396,7 +2396,7 @@ +@@ -2440,7 +2440,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -583,7 +561,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2410,7 +2410,7 @@ +@@ -2454,7 +2454,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 6 VARIABLE_SCOPE GLOBAL @@ -592,7 +570,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2420,9 +2420,9 @@ +@@ -2464,9 +2464,9 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MAX_SORT_FILE_SIZE SESSION_VALUE NULL @@ -604,7 +582,7 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't use the fast sort index method to created index if the temporary file would get bigger than this -@@ -2434,14 +2434,14 @@ +@@ -2478,14 +2478,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MMAP_SIZE SESSION_VALUE NULL @@ -622,7 +600,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -2466,10 +2466,10 @@ +@@ -2510,10 +2510,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -635,7 +613,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2483,7 +2483,7 @@ +@@ -2527,7 +2527,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -644,7 +622,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2536,7 +2536,7 @@ +@@ -2580,7 +2580,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -653,7 +631,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2550,7 +2550,7 @@ +@@ -2594,7 +2594,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 30 VARIABLE_SCOPE SESSION @@ -662,7 +640,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2564,7 +2564,7 @@ +@@ -2608,7 +2608,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE SESSION @@ -671,7 +649,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2578,7 +2578,7 @@ +@@ -2622,7 +2622,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 60 VARIABLE_SCOPE SESSION @@ -680,7 +658,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2648,7 +2648,7 @@ +@@ -2692,7 +2692,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -689,7 +667,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2662,7 +2662,7 @@ +@@ -2706,7 +2706,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 62 VARIABLE_SCOPE SESSION @@ -698,7 +676,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2676,7 +2676,7 @@ +@@ -2720,7 +2720,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE SESSION @@ -707,16 +685,29 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2704,7 +2704,7 @@ +@@ -2762,10 +2762,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 1 + DEFAULT_VALUE 1048576 + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum allowed size of an optimizer trace + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -2776,7 +2776,7 @@ + GLOBAL_VALUE_ORIGIN COMPILE-TIME + DEFAULT_VALUE 4 VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2732,7 +2732,7 @@ +@@ -2804,7 +2804,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -725,7 +716,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2746,7 +2746,7 @@ +@@ -2818,7 +2818,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -734,7 +725,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 200 -@@ -2760,7 +2760,7 @@ +@@ -2832,7 +2832,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -743,7 +734,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2774,7 +2774,7 @@ +@@ -2846,7 +2846,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -752,7 +743,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2788,7 +2788,7 @@ +@@ -2860,7 +2860,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -761,7 +752,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2802,7 +2802,7 @@ +@@ -2874,7 +2874,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -770,7 +761,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2816,7 +2816,7 @@ +@@ -2888,7 +2888,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -779,7 +770,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2830,7 +2830,7 @@ +@@ -2902,7 +2902,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -788,7 +779,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2844,7 +2844,7 @@ +@@ -2916,7 +2916,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -797,7 +788,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2858,7 +2858,7 @@ +@@ -2930,7 +2930,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 80 VARIABLE_SCOPE GLOBAL @@ -806,7 +797,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2872,7 +2872,7 @@ +@@ -2944,7 +2944,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -815,7 +806,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2886,7 +2886,7 @@ +@@ -2958,7 +2958,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -824,7 +815,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2900,7 +2900,7 @@ +@@ -2972,7 +2972,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -833,7 +824,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2914,7 +2914,7 @@ +@@ -2986,7 +2986,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE GLOBAL @@ -842,7 +833,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -2928,7 +2928,7 @@ +@@ -3000,7 +3000,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -851,7 +842,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2942,7 +2942,7 @@ +@@ -3014,7 +3014,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 200 VARIABLE_SCOPE GLOBAL @@ -860,7 +851,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2956,7 +2956,7 @@ +@@ -3028,7 +3028,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -869,7 +860,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2970,7 +2970,7 @@ +@@ -3042,7 +3042,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 40 VARIABLE_SCOPE GLOBAL @@ -878,7 +869,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -2984,7 +2984,7 @@ +@@ -3056,7 +3056,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -887,7 +878,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -2998,7 +2998,7 @@ +@@ -3070,7 +3070,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -896,7 +887,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3012,7 +3012,7 @@ +@@ -3084,7 +3084,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -905,7 +896,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3026,7 +3026,7 @@ +@@ -3098,7 +3098,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 160 VARIABLE_SCOPE GLOBAL @@ -914,16 +905,16 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3040,7 +3040,7 @@ +@@ -3112,7 +3112,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 191 + DEFAULT_VALUE 202 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3054,7 +3054,7 @@ +@@ -3126,7 +3126,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -932,7 +923,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3068,7 +3068,7 @@ +@@ -3140,7 +3140,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -941,7 +932,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3082,7 +3082,7 @@ +@@ -3154,7 +3154,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -950,7 +941,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3096,7 +3096,7 @@ +@@ -3168,7 +3168,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -959,7 +950,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3110,7 +3110,7 @@ +@@ -3182,7 +3182,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -968,7 +959,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3124,7 +3124,7 @@ +@@ -3196,7 +3196,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -977,7 +968,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -3138,7 +3138,7 @@ +@@ -3210,7 +3210,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -986,7 +977,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -3152,7 +3152,7 @@ +@@ -3224,7 +3224,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -995,7 +986,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3222,7 +3222,7 @@ +@@ -3280,7 +3280,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE SESSION @@ -1004,7 +995,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3250,7 +3250,7 @@ +@@ -3308,7 +3308,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 15 VARIABLE_SCOPE SESSION @@ -1013,7 +1004,7 @@ VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -3264,7 +3264,7 @@ +@@ -3322,7 +3322,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 5 VARIABLE_SCOPE SESSION @@ -1022,7 +1013,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3348,7 +3348,7 @@ +@@ -3406,7 +3406,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -1031,7 +1022,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3362,7 +3362,7 @@ +@@ -3420,7 +3420,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -1040,7 +1031,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3376,7 +3376,7 @@ +@@ -3434,7 +3434,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE GLOBAL @@ -1049,7 +1040,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3393,7 +3393,7 @@ +@@ -3451,7 +3451,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1058,7 +1049,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3446,7 +3446,7 @@ +@@ -3504,7 +3504,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 24576 VARIABLE_SCOPE SESSION @@ -1067,7 +1058,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3460,7 +3460,7 @@ +@@ -3518,7 +3518,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1076,7 +1067,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3474,7 +3474,7 @@ +@@ -3532,7 +3532,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 131072 VARIABLE_SCOPE SESSION @@ -1085,7 +1076,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3502,7 +3502,7 @@ +@@ -3560,7 +3560,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -1094,7 +1085,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -3516,10 +3516,10 @@ +@@ -3574,10 +3574,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8388608 VARIABLE_SCOPE SESSION @@ -1107,7 +1098,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3558,7 +3558,7 @@ +@@ -3630,7 +3630,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -1116,7 +1107,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -3656,7 +3656,7 @@ +@@ -3728,7 +3728,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL @@ -1125,7 +1116,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3670,7 +3670,7 @@ +@@ -3742,7 +3742,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE GLOBAL @@ -1134,7 +1125,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -3729,7 +3729,7 @@ +@@ -3801,7 +3801,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1143,7 +1134,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4020,7 +4020,7 @@ +@@ -4092,7 +4092,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL @@ -1152,7 +1143,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -4090,7 +4090,7 @@ +@@ -4190,7 +4190,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 400 VARIABLE_SCOPE GLOBAL @@ -1160,17 +1151,17 @@ +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 - NUMERIC_MAX_VALUE 524288 -@@ -4104,7 +4104,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME + NUMERIC_MAX_VALUE 2097152 +@@ -4204,7 +4204,7 @@ + GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 2000 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of cached open tables - NUMERIC_MIN_VALUE 1 + NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -4174,7 +4174,7 @@ +@@ -4288,7 +4288,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL @@ -1179,7 +1170,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -4188,7 +4188,7 @@ +@@ -4302,7 +4302,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -1188,7 +1179,7 @@ VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 512 -@@ -4295,15 +4295,15 @@ +@@ -4409,15 +4409,15 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TMP_DISK_TABLE_SIZE @@ -1208,7 +1199,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4317,7 +4317,7 @@ +@@ -4431,7 +4431,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size. NUMERIC_MIN_VALUE 1024 @@ -1217,7 +1208,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4331,7 +4331,7 @@ +@@ -4445,7 +4445,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1226,7 +1217,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4342,7 +4342,7 @@ +@@ -4456,7 +4456,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8192 VARIABLE_SCOPE SESSION @@ -1235,7 +1226,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4356,7 +4356,7 @@ +@@ -4470,7 +4470,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1244,7 +1235,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -4454,7 +4454,7 @@ +@@ -4568,7 +4568,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 28800 VARIABLE_SCOPE SESSION @@ -1253,7 +1244,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -4559,7 +4559,7 @@ +@@ -4673,7 +4673,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -1262,7 +1253,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -4572,7 +4572,7 @@ +@@ -4686,7 +4686,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1271,7 +1262,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4582,7 +4582,7 @@ +@@ -4696,7 +4696,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1280,7 +1271,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4677,7 +4677,7 @@ +@@ -4791,7 +4791,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 926ac8b2668..c896df1808f 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -2742,6 +2742,34 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME OPTIMIZER_TRACE +SESSION_VALUE enabled=off +GLOBAL_VALUE enabled=off +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE enabled=off +VARIABLE_SCOPE SESSION +VARIABLE_TYPE FLAGSET +VARIABLE_COMMENT Controls tracing of the Optimizer: optimizer_trace=option=val[,option=val...], where option is one of {enabled} and val is one of {on, off, default} +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST enabled,default +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE +SESSION_VALUE 1048576 +GLOBAL_VALUE 1048576 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 1048576 +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Maximum allowed size of an optimizer trace +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY SESSION_VALUE 4 GLOBAL_VALUE 4 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff index cb9e84b81c8..53a74f90032 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded,32bit.rdiff @@ -1,6 +1,6 @@ ---- sysvars_server_notembedded.result 2017-12-15 20:57:40.174654761 +0200 -+++ sysvars_server_notembedded,32bit.reject 2017-12-15 21:02:20.476044700 +0200 -@@ -58,7 +58,7 @@ +--- suite/sys_vars/r/sysvars_server_notembedded.result 2019-02-09 18:56:57.338345161 +0530 ++++ suite/sys_vars/r/sysvars_server_notembedded,32bit.reject 2019-02-09 22:24:33.663762812 +0530 +@@ -74,7 +74,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -9,7 +9,7 @@ VARIABLE_COMMENT Auto-increment columns are incremented by this NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 65535 -@@ -72,7 +72,7 @@ +@@ -88,7 +88,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -18,7 +18,7 @@ VARIABLE_COMMENT Offset added to Auto-increment columns. Used when auto-increment-increment != 1 NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 65535 -@@ -86,7 +86,7 @@ +@@ -102,7 +102,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 150 VARIABLE_SCOPE GLOBAL @@ -27,7 +27,7 @@ VARIABLE_COMMENT The number of outstanding connection requests MariaDB can have. This comes into play when the main MariaDB thread gets very many connection requests in a very short time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -159,7 +159,7 @@ +@@ -175,7 +175,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the transactional cache for updates to transactional engines for the binary log. If you often use transactions containing many statements, you can increase this to get more performance NUMERIC_MIN_VALUE 4096 @@ -36,7 +36,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -184,10 +184,10 @@ +@@ -200,10 +200,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -49,7 +49,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -198,10 +198,10 @@ +@@ -214,10 +214,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100000 VARIABLE_SCOPE GLOBAL @@ -62,7 +62,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -229,7 +229,7 @@ +@@ -245,7 +245,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of file cache for the binary log NUMERIC_MIN_VALUE 8192 @@ -71,7 +71,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -285,7 +285,7 @@ +@@ -301,7 +301,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the statement cache for updates to non-transactional engines for the binary log. If you often use statements updating a great number of rows, you can increase this to get more performance. NUMERIC_MIN_VALUE 4096 @@ -80,7 +80,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -299,7 +299,7 @@ +@@ -315,7 +315,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread! NUMERIC_MIN_VALUE 0 @@ -89,7 +89,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -562,7 +562,7 @@ +@@ -578,7 +578,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -98,7 +98,7 @@ VARIABLE_COMMENT The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake' NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 31536000 -@@ -618,7 +618,7 @@ +@@ -648,7 +648,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 15 VARIABLE_SCOPE SESSION @@ -107,7 +107,7 @@ VARIABLE_COMMENT Long search depth for the two-step deadlock detection NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 33 -@@ -632,7 +632,7 @@ +@@ -662,7 +662,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4 VARIABLE_SCOPE SESSION @@ -116,7 +116,7 @@ VARIABLE_COMMENT Short search depth for the two-step deadlock detection NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 32 -@@ -646,7 +646,7 @@ +@@ -676,7 +676,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50000000 VARIABLE_SCOPE SESSION @@ -125,7 +125,7 @@ VARIABLE_COMMENT Long timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -660,7 +660,7 @@ +@@ -690,7 +690,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10000 VARIABLE_SCOPE SESSION @@ -134,7 +134,7 @@ VARIABLE_COMMENT Short timeout for the two-step deadlock detection (in microseconds) NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -730,7 +730,7 @@ +@@ -760,7 +760,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -143,7 +143,7 @@ VARIABLE_COMMENT The default week format used by WEEK() functions NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 7 -@@ -744,7 +744,7 @@ +@@ -774,7 +774,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -152,7 +152,7 @@ VARIABLE_COMMENT After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -758,7 +758,7 @@ +@@ -788,7 +788,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 300 VARIABLE_SCOPE GLOBAL @@ -161,7 +161,7 @@ VARIABLE_COMMENT How long a INSERT DELAYED thread should wait for INSERT statements before terminating NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -772,7 +772,7 @@ +@@ -802,7 +802,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1000 VARIABLE_SCOPE GLOBAL @@ -170,7 +170,7 @@ VARIABLE_COMMENT What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -800,7 +800,7 @@ +@@ -830,7 +830,7 @@ GLOBAL_VALUE_ORIGIN SQL DEFAULT_VALUE 4 VARIABLE_SCOPE SESSION @@ -179,7 +179,7 @@ VARIABLE_COMMENT Precision of the result of '/' operator will be increased on that value NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 38 -@@ -912,7 +912,7 @@ +@@ -956,7 +956,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -188,7 +188,7 @@ VARIABLE_COMMENT If non-zero, binary logs will be purged after expire_logs_days days; possible purges happen at startup and at binary log rotation NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 99 -@@ -954,7 +954,7 @@ +@@ -998,7 +998,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE GLOBAL @@ -197,7 +197,7 @@ VARIABLE_COMMENT The number of connections on extra-port NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 100000 -@@ -996,7 +996,7 @@ +@@ -1040,7 +1040,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -206,7 +206,7 @@ VARIABLE_COMMENT A dedicated thread is created to flush all tables at the given interval NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -1038,7 +1038,7 @@ +@@ -1082,7 +1082,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 84 VARIABLE_SCOPE GLOBAL @@ -215,7 +215,7 @@ VARIABLE_COMMENT The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 84 -@@ -1052,7 +1052,7 @@ +@@ -1096,7 +1096,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4 VARIABLE_SCOPE GLOBAL @@ -224,7 +224,7 @@ VARIABLE_COMMENT The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 84 -@@ -1066,7 +1066,7 @@ +@@ -1110,7 +1110,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 20 VARIABLE_SCOPE GLOBAL @@ -233,7 +233,7 @@ VARIABLE_COMMENT Number of best matches to use for query expansion NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1000 -@@ -1125,7 +1125,7 @@ +@@ -1169,7 +1169,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The maximum length of the result of function GROUP_CONCAT() NUMERIC_MIN_VALUE 4 @@ -242,7 +242,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1374,7 +1374,7 @@ +@@ -1432,7 +1432,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -251,7 +251,7 @@ VARIABLE_COMMENT Number of bytes used for a histogram. If set to 0, no histograms are created by ANALYZE. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -1402,7 +1402,7 @@ +@@ -1460,7 +1460,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 128 VARIABLE_SCOPE GLOBAL @@ -260,7 +260,7 @@ VARIABLE_COMMENT How many host names should be cached to avoid resolving. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65536 -@@ -1556,7 +1556,7 @@ +@@ -1614,7 +1614,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 28800 VARIABLE_SCOPE SESSION @@ -269,20 +269,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on an interactive connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -1570,10 +1570,10 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 1000 - VARIABLE_SCOPE SESSION --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT The minimum number of scalar elements in the value list of IN predicate that triggers its conversion to IN subquery - NUMERIC_MIN_VALUE 0 --NUMERIC_MAX_VALUE 18446744073709551615 -+NUMERIC_MAX_VALUE 4294967295 - NUMERIC_BLOCK_SIZE 1 - ENUM_VALUE_LIST NULL - READ_ONLY NO -@@ -1601,7 +1601,7 @@ +@@ -1645,7 +1645,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer that is used for joins NUMERIC_MIN_VALUE 128 @@ -291,7 +278,7 @@ NUMERIC_BLOCK_SIZE 128 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1626,7 +1626,7 @@ +@@ -1670,7 +1670,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE SESSION @@ -300,7 +287,7 @@ VARIABLE_COMMENT Controls what join operations can be executed with join buffers. Odd numbers are used for plain join buffers while even numbers are used for linked buffers NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 8 -@@ -1657,7 +1657,7 @@ +@@ -1701,7 +1701,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford NUMERIC_MIN_VALUE 0 @@ -309,7 +296,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -1878,7 +1878,7 @@ +@@ -1922,7 +1922,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 86400 VARIABLE_SCOPE SESSION @@ -318,7 +305,7 @@ VARIABLE_COMMENT Timeout in seconds to wait for a lock before returning an error. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -2088,7 +2088,7 @@ +@@ -2132,7 +2132,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -327,7 +314,7 @@ VARIABLE_COMMENT Write to slow log every #th slow query. Set to 1 to log everything. Increase it to reduce the size of the slow or the performance impact of slow logging NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2130,7 +2130,7 @@ +@@ -2174,7 +2174,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE SESSION @@ -336,7 +323,7 @@ VARIABLE_COMMENT Log some not critical warnings to the general log file.Value can be between 0 and 11. Higher values mean more verbosity NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2186,7 +2186,7 @@ +@@ -2230,7 +2230,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16777216 VARIABLE_SCOPE SESSION @@ -345,7 +332,7 @@ VARIABLE_COMMENT Max packet length to send to or receive from the server NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -2196,14 +2196,14 @@ +@@ -2240,14 +2240,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_BINLOG_CACHE_SIZE SESSION_VALUE NULL @@ -363,7 +350,7 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2214,7 +2214,7 @@ +@@ -2258,7 +2258,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL @@ -372,7 +359,7 @@ VARIABLE_COMMENT Binary log will be rotated automatically when the size exceeds this value. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 1073741824 -@@ -2224,14 +2224,14 @@ +@@ -2268,14 +2268,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MAX_BINLOG_STMT_CACHE_SIZE SESSION_VALUE NULL @@ -390,16 +377,16 @@ NUMERIC_BLOCK_SIZE 4096 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2242,7 +2242,7 @@ +@@ -2286,7 +2286,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 151 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of simultaneous clients allowed - NUMERIC_MIN_VALUE 1 + NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 100000 -@@ -2256,7 +2256,7 @@ +@@ -2300,7 +2300,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -408,7 +395,7 @@ VARIABLE_COMMENT If there is more than this number of interrupted connections from a host this host will be blocked from further connections NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2270,7 +2270,7 @@ +@@ -2314,7 +2314,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 20 VARIABLE_SCOPE SESSION @@ -417,7 +404,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -2298,7 +2298,7 @@ +@@ -2342,7 +2342,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 64 VARIABLE_SCOPE SESSION @@ -426,7 +413,7 @@ VARIABLE_COMMENT Max number of errors/warnings to store for a statement NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 65535 -@@ -2315,7 +2315,7 @@ +@@ -2359,7 +2359,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't allow creation of heap tables bigger than this NUMERIC_MIN_VALUE 16384 @@ -435,7 +422,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2326,7 +2326,7 @@ +@@ -2370,7 +2370,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 20 VARIABLE_SCOPE SESSION @@ -444,7 +431,7 @@ VARIABLE_COMMENT Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero INSERT DELAYED will be not used NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -2354,7 +2354,7 @@ +@@ -2398,7 +2398,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE SESSION @@ -453,7 +440,7 @@ VARIABLE_COMMENT Max number of bytes in sorted records NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -2368,7 +2368,7 @@ +@@ -2412,7 +2412,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -462,16 +449,7 @@ VARIABLE_COMMENT The maximum BLOB length to send to server from mysql_send_long_data API. Deprecated option; use max_allowed_packet instead. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -2382,7 +2382,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 16382 - VARIABLE_SCOPE GLOBAL --VARIABLE_TYPE BIGINT UNSIGNED -+VARIABLE_TYPE INT UNSIGNED - VARIABLE_COMMENT Maximum number of prepared statements in the server - NUMERIC_MIN_VALUE 0 - NUMERIC_MAX_VALUE 1048576 -@@ -2396,7 +2396,7 @@ +@@ -2454,7 +2454,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE SESSION @@ -480,7 +458,7 @@ VARIABLE_COMMENT Maximum number of iterations when executing recursive queries NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2424,7 +2424,7 @@ +@@ -2482,7 +2482,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE SESSION @@ -489,7 +467,7 @@ VARIABLE_COMMENT Limit assumed max number of seeks when looking up rows based on a key NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2452,7 +2452,7 @@ +@@ -2510,7 +2510,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE SESSION @@ -498,7 +476,7 @@ VARIABLE_COMMENT The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored) NUMERIC_MIN_VALUE 4 NUMERIC_MAX_VALUE 8388608 -@@ -2466,7 +2466,7 @@ +@@ -2524,7 +2524,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -507,7 +485,7 @@ VARIABLE_COMMENT Maximum stored procedure recursion depth NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 255 -@@ -2494,7 +2494,7 @@ +@@ -2552,7 +2552,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32 VARIABLE_SCOPE SESSION @@ -516,7 +494,7 @@ VARIABLE_COMMENT Unused, will be removed. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2522,7 +2522,7 @@ +@@ -2580,7 +2580,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4294967295 VARIABLE_SCOPE GLOBAL @@ -525,7 +503,7 @@ VARIABLE_COMMENT After this many write locks, allow some read locks to run in between NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2536,7 +2536,7 @@ +@@ -2594,7 +2594,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -534,7 +512,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1048576 -@@ -2550,7 +2550,7 @@ +@@ -2608,7 +2608,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8 VARIABLE_SCOPE GLOBAL @@ -543,7 +521,7 @@ VARIABLE_COMMENT Unused NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 1024 -@@ -2564,7 +2564,7 @@ +@@ -2622,7 +2622,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE SESSION @@ -552,7 +530,7 @@ VARIABLE_COMMENT Don't write queries to slow log that examine fewer rows than that NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -2578,7 +2578,7 @@ +@@ -2636,7 +2636,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -561,7 +539,7 @@ VARIABLE_COMMENT Size of buffer to use when using MRR with range access NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -2592,10 +2592,10 @@ +@@ -2650,10 +2650,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE SESSION @@ -574,7 +552,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2606,7 +2606,7 @@ +@@ -2664,7 +2664,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -583,7 +561,7 @@ VARIABLE_COMMENT Block size to be used for MyISAM index pages NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 16384 -@@ -2620,7 +2620,7 @@ +@@ -2678,7 +2678,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 6 VARIABLE_SCOPE GLOBAL @@ -592,7 +570,7 @@ VARIABLE_COMMENT Default pointer size to be used for MyISAM tables NUMERIC_MIN_VALUE 2 NUMERIC_MAX_VALUE 7 -@@ -2630,9 +2630,9 @@ +@@ -2688,9 +2688,9 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MAX_SORT_FILE_SIZE SESSION_VALUE NULL @@ -604,7 +582,7 @@ VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Don't use the fast sort index method to created index if the temporary file would get bigger than this -@@ -2644,14 +2644,14 @@ +@@ -2702,14 +2702,14 @@ COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME MYISAM_MMAP_SIZE SESSION_VALUE NULL @@ -622,7 +600,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY YES -@@ -2676,10 +2676,10 @@ +@@ -2734,10 +2734,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -635,7 +613,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2693,7 +2693,7 @@ +@@ -2751,7 +2751,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE NUMERIC_MIN_VALUE 4096 @@ -644,7 +622,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -2746,7 +2746,7 @@ +@@ -2804,7 +2804,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -653,7 +631,7 @@ VARIABLE_COMMENT Buffer length for TCP/IP and socket communication NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1048576 -@@ -2760,7 +2760,7 @@ +@@ -2818,7 +2818,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 30 VARIABLE_SCOPE SESSION @@ -662,7 +640,7 @@ VARIABLE_COMMENT Number of seconds to wait for more data from a connection before aborting the read NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2774,7 +2774,7 @@ +@@ -2832,7 +2832,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE SESSION @@ -671,7 +649,7 @@ VARIABLE_COMMENT If a read on a communication port is interrupted, retry this many times before giving up NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -2788,7 +2788,7 @@ +@@ -2846,7 +2846,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 60 VARIABLE_SCOPE SESSION @@ -680,7 +658,7 @@ VARIABLE_COMMENT Number of seconds to wait for a block to be written to a connection before aborting the write NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -2858,7 +2858,7 @@ +@@ -2916,7 +2916,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -689,7 +667,7 @@ VARIABLE_COMMENT Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1 -@@ -2872,7 +2872,7 @@ +@@ -2930,7 +2930,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 62 VARIABLE_SCOPE SESSION @@ -698,7 +676,7 @@ VARIABLE_COMMENT Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Values smaller than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 62 -@@ -2886,7 +2886,7 @@ +@@ -2944,7 +2944,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE SESSION @@ -707,16 +685,29 @@ VARIABLE_COMMENT Controls number of record samples to check condition selectivity NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 4294967295 -@@ -2914,7 +2914,7 @@ +@@ -2986,10 +2986,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 1 + DEFAULT_VALUE 1048576 + VARIABLE_SCOPE SESSION +-VARIABLE_TYPE BIGINT UNSIGNED ++VARIABLE_TYPE INT UNSIGNED + VARIABLE_COMMENT Maximum allowed size of an optimizer trace + NUMERIC_MIN_VALUE 0 +-NUMERIC_MAX_VALUE 18446744073709551615 ++NUMERIC_MAX_VALUE 4294967295 + NUMERIC_BLOCK_SIZE 1 + ENUM_VALUE_LIST NULL + READ_ONLY NO +@@ -3000,7 +3000,7 @@ + GLOBAL_VALUE_ORIGIN COMPILE-TIME + DEFAULT_VALUE 4 VARIABLE_SCOPE SESSION -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Controls selectivity of which conditions the optimizer takes into account to calculate cardinality of a partial join when it searches for the best execution plan Meaning: 1 - use selectivity of index backed range conditions to calculate the cardinality of a partial join if the last joined table is accessed by full table scan or an index scan, 2 - use selectivity of index backed range conditions to calculate the cardinality of a partial join in any case, 3 - additionally always use selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join, 4 - use histograms to calculate selectivity of range conditions that are not backed by any index to calculate the cardinality of a partial join.5 - additionally use selectivity of certain non-range predicates calculated on record samples NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 5 -@@ -2942,7 +2942,7 @@ +@@ -3028,7 +3028,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -725,7 +716,7 @@ VARIABLE_COMMENT Maximum number of instrumented user@host accounts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2956,7 +2956,7 @@ +@@ -3042,7 +3042,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -734,7 +725,7 @@ VARIABLE_COMMENT Size of the statement digest. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 200 -@@ -2970,7 +2970,7 @@ +@@ -3056,7 +3056,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -743,7 +734,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STAGES_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -2984,7 +2984,7 @@ +@@ -3070,7 +3070,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -752,7 +743,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STAGES_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -2998,7 +2998,7 @@ +@@ -3084,7 +3084,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -761,7 +752,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_STATEMENTS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3012,7 +3012,7 @@ +@@ -3098,7 +3098,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -770,7 +761,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_STATEMENTS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -3026,7 +3026,7 @@ +@@ -3112,7 +3112,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -779,7 +770,7 @@ VARIABLE_COMMENT Number of rows in EVENTS_WAITS_HISTORY_LONG. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3040,7 +3040,7 @@ +@@ -3126,7 +3126,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -788,7 +779,7 @@ VARIABLE_COMMENT Number of rows per thread in EVENTS_WAITS_HISTORY. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1024 -@@ -3054,7 +3054,7 @@ +@@ -3140,7 +3140,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -797,7 +788,7 @@ VARIABLE_COMMENT Maximum number of instrumented hosts. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3068,7 +3068,7 @@ +@@ -3154,7 +3154,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 80 VARIABLE_SCOPE GLOBAL @@ -806,7 +797,7 @@ VARIABLE_COMMENT Maximum number of condition instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3082,7 +3082,7 @@ +@@ -3168,7 +3168,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -815,7 +806,7 @@ VARIABLE_COMMENT Maximum number of instrumented condition objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3096,7 +3096,7 @@ +@@ -3182,7 +3182,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1024 VARIABLE_SCOPE GLOBAL @@ -824,7 +815,7 @@ VARIABLE_COMMENT Maximum length considered for digest text, when stored in performance_schema tables. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -3110,7 +3110,7 @@ +@@ -3196,7 +3196,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -833,7 +824,7 @@ VARIABLE_COMMENT Maximum number of file instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3124,7 +3124,7 @@ +@@ -3210,7 +3210,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE GLOBAL @@ -842,7 +833,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented files. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -3138,7 +3138,7 @@ +@@ -3224,7 +3224,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -851,7 +842,7 @@ VARIABLE_COMMENT Maximum number of instrumented files. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3152,7 +3152,7 @@ +@@ -3238,7 +3238,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 200 VARIABLE_SCOPE GLOBAL @@ -860,7 +851,7 @@ VARIABLE_COMMENT Maximum number of mutex instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3166,7 +3166,7 @@ +@@ -3252,7 +3252,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -869,7 +860,7 @@ VARIABLE_COMMENT Maximum number of instrumented MUTEX objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -3180,7 +3180,7 @@ +@@ -3266,7 +3266,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 40 VARIABLE_SCOPE GLOBAL @@ -878,7 +869,7 @@ VARIABLE_COMMENT Maximum number of rwlock instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3194,7 +3194,7 @@ +@@ -3280,7 +3280,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -887,7 +878,7 @@ VARIABLE_COMMENT Maximum number of instrumented RWLOCK objects. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 104857600 -@@ -3208,7 +3208,7 @@ +@@ -3294,7 +3294,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -896,7 +887,7 @@ VARIABLE_COMMENT Maximum number of socket instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3222,7 +3222,7 @@ +@@ -3308,7 +3308,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -905,7 +896,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented sockets. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3236,7 +3236,7 @@ +@@ -3322,7 +3322,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 160 VARIABLE_SCOPE GLOBAL @@ -914,16 +905,16 @@ VARIABLE_COMMENT Maximum number of stage instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3250,7 +3250,7 @@ +@@ -3336,7 +3336,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME - DEFAULT_VALUE 191 + DEFAULT_VALUE 202 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT Maximum number of statement instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3264,7 +3264,7 @@ +@@ -3350,7 +3350,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -932,7 +923,7 @@ VARIABLE_COMMENT Maximum number of opened instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3278,7 +3278,7 @@ +@@ -3364,7 +3364,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -941,7 +932,7 @@ VARIABLE_COMMENT Maximum number of instrumented tables. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3292,7 +3292,7 @@ +@@ -3378,7 +3378,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 50 VARIABLE_SCOPE GLOBAL @@ -950,7 +941,7 @@ VARIABLE_COMMENT Maximum number of thread instruments. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 256 -@@ -3306,7 +3306,7 @@ +@@ -3392,7 +3392,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -959,7 +950,7 @@ VARIABLE_COMMENT Maximum number of instrumented threads. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3320,7 +3320,7 @@ +@@ -3406,7 +3406,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -968,7 +959,7 @@ VARIABLE_COMMENT Size of session attribute string buffer per thread. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3334,7 +3334,7 @@ +@@ -3420,7 +3420,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -977,7 +968,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_ACTORS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1024 -@@ -3348,7 +3348,7 @@ +@@ -3434,7 +3434,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 100 VARIABLE_SCOPE GLOBAL @@ -986,7 +977,7 @@ VARIABLE_COMMENT Maximum number of rows in SETUP_OBJECTS. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 1048576 -@@ -3362,7 +3362,7 @@ +@@ -3448,7 +3448,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE -1 VARIABLE_SCOPE GLOBAL @@ -995,7 +986,7 @@ VARIABLE_COMMENT Maximum number of instrumented users. Use 0 to disable, -1 for automated sizing. NUMERIC_MIN_VALUE -1 NUMERIC_MAX_VALUE 1048576 -@@ -3432,7 +3432,7 @@ +@@ -3504,7 +3504,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32768 VARIABLE_SCOPE SESSION @@ -1004,7 +995,7 @@ VARIABLE_COMMENT The size of the buffer that is allocated when preloading indexes NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -3460,7 +3460,7 @@ +@@ -3532,7 +3532,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 15 VARIABLE_SCOPE SESSION @@ -1013,7 +1004,7 @@ VARIABLE_COMMENT Number of statements about which profiling information is maintained. If set to 0, no profiles are stored. See SHOW PROFILES. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 100 -@@ -3474,7 +3474,7 @@ +@@ -3546,7 +3546,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 5 VARIABLE_SCOPE SESSION @@ -1022,7 +1013,7 @@ VARIABLE_COMMENT Seconds between sending progress reports to the client for time-consuming statements. Set to 0 to disable progress reporting. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3558,7 +3558,7 @@ +@@ -3630,7 +3630,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 16384 VARIABLE_SCOPE SESSION @@ -1031,7 +1022,7 @@ VARIABLE_COMMENT Allocation block size for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3572,7 +3572,7 @@ +@@ -3644,7 +3644,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1048576 VARIABLE_SCOPE GLOBAL @@ -1040,7 +1031,7 @@ VARIABLE_COMMENT Don't cache results that are bigger than this NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3586,7 +3586,7 @@ +@@ -3658,7 +3658,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE GLOBAL @@ -1049,7 +1040,7 @@ VARIABLE_COMMENT The minimum size for blocks allocated by the query cache NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -3603,7 +3603,7 @@ +@@ -3675,7 +3675,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT The memory allocated to store results from old queries NUMERIC_MIN_VALUE 0 @@ -1058,7 +1049,7 @@ NUMERIC_BLOCK_SIZE 1024 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3656,7 +3656,7 @@ +@@ -3728,7 +3728,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 24576 VARIABLE_SCOPE SESSION @@ -1067,7 +1058,7 @@ VARIABLE_COMMENT Persistent buffer for query parsing and execution NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 4294967295 -@@ -3670,7 +3670,7 @@ +@@ -3742,7 +3742,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1076,7 +1067,7 @@ VARIABLE_COMMENT Allocation block size for storing ranges during optimization NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 4294967295 -@@ -3687,7 +3687,7 @@ +@@ -3759,7 +3759,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Maximum speed(KB/s) to read binlog from master (0 = no limit) NUMERIC_MIN_VALUE 0 @@ -1085,7 +1076,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -3698,7 +3698,7 @@ +@@ -3770,7 +3770,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 131072 VARIABLE_SCOPE SESSION @@ -1094,7 +1085,7 @@ VARIABLE_COMMENT Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value NUMERIC_MIN_VALUE 8192 NUMERIC_MAX_VALUE 2147483647 -@@ -3726,7 +3726,7 @@ +@@ -3798,7 +3798,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 262144 VARIABLE_SCOPE SESSION @@ -1103,7 +1094,7 @@ VARIABLE_COMMENT When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 2147483647 -@@ -4006,10 +4006,10 @@ +@@ -4078,10 +4078,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8388608 VARIABLE_SCOPE SESSION @@ -1116,7 +1107,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4034,10 +4034,10 @@ +@@ -4106,10 +4106,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10000 VARIABLE_SCOPE GLOBAL @@ -1129,7 +1120,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4048,10 +4048,10 @@ +@@ -4120,10 +4120,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32 VARIABLE_SCOPE GLOBAL @@ -1142,7 +1133,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4132,10 +4132,10 @@ +@@ -4204,10 +4204,10 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 32 VARIABLE_SCOPE GLOBAL @@ -1155,7 +1146,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4174,7 +4174,7 @@ +@@ -4260,7 +4260,7 @@ GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 1 VARIABLE_SCOPE SESSION @@ -1164,7 +1155,7 @@ VARIABLE_COMMENT Uniquely identifies the server instance in the community of replication partners NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 4294967295 -@@ -4356,7 +4356,7 @@ +@@ -4442,7 +4442,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1173,7 +1164,7 @@ VARIABLE_COMMENT Maximum number of parallel threads to use on slave for events in a single replication domain. When using multiple domains, this can be used to limit a single domain from grabbing all threads and thus stalling other domains. The default of 0 means to allow a domain to grab as many threads as it wants, up to the value of slave_parallel_threads. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -4398,7 +4398,7 @@ +@@ -4484,7 +4484,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 1073741824 VARIABLE_SCOPE GLOBAL @@ -1182,7 +1173,7 @@ VARIABLE_COMMENT The maximum packet length to sent successfully from the master to slave. NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 1073741824 -@@ -4426,7 +4426,7 @@ +@@ -4512,7 +4512,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 131072 VARIABLE_SCOPE GLOBAL @@ -1191,7 +1182,7 @@ VARIABLE_COMMENT Limit on how much memory SQL threads should use per parallel replication thread when reading ahead in the relay log looking for opportunities for parallel replication. Only used when --slave-parallel-threads > 0. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 2147483647 -@@ -4454,7 +4454,7 @@ +@@ -4540,7 +4540,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1200,7 +1191,7 @@ VARIABLE_COMMENT If non-zero, number of threads to spawn to apply in parallel events on the slave that were group-committed on the master or were logged with GTID in different replication domains. Note that these threads are in addition to the IO and SQL threads, which are always created by a replication slave NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -4468,7 +4468,7 @@ +@@ -4554,7 +4554,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1209,7 +1200,7 @@ VARIABLE_COMMENT Alias for slave_parallel_threads NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16383 -@@ -4524,7 +4524,7 @@ +@@ -4610,7 +4610,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -1218,7 +1209,7 @@ VARIABLE_COMMENT Number of times the slave SQL thread will retry a transaction in case it failed with a deadlock, elapsed lock wait timeout or listed in slave_transaction_retry_errors, before giving up and stopping NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -4552,7 +4552,7 @@ +@@ -4638,7 +4638,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 0 VARIABLE_SCOPE GLOBAL @@ -1227,7 +1218,7 @@ VARIABLE_COMMENT Interval of the slave SQL thread will retry a transaction in case it failed with a deadlock or elapsed lock wait timeout or listed in slave_transaction_retry_errors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 3600 -@@ -4580,7 +4580,7 @@ +@@ -4666,7 +4666,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 2 VARIABLE_SCOPE GLOBAL @@ -1236,7 +1227,7 @@ VARIABLE_COMMENT If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 31536000 -@@ -4639,7 +4639,7 @@ +@@ -4725,7 +4725,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Each thread that needs to do a sort allocates a buffer of this size NUMERIC_MIN_VALUE 1024 @@ -1245,7 +1236,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -4944,7 +4944,7 @@ +@@ -5030,7 +5030,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL @@ -1254,7 +1245,7 @@ VARIABLE_COMMENT The soft upper limit for number of cached stored routines for one connection. NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 524288 -@@ -5042,7 +5042,7 @@ +@@ -5156,7 +5156,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 400 VARIABLE_SCOPE GLOBAL @@ -1262,17 +1253,17 @@ +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of cached table definitions NUMERIC_MIN_VALUE 400 - NUMERIC_MAX_VALUE 524288 -@@ -5056,7 +5056,7 @@ - GLOBAL_VALUE_ORIGIN COMPILE-TIME + NUMERIC_MAX_VALUE 2097152 +@@ -5170,7 +5170,7 @@ + GLOBAL_VALUE_ORIGIN CONFIG DEFAULT_VALUE 2000 VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_TYPE INT UNSIGNED VARIABLE_COMMENT The number of cached open tables - NUMERIC_MIN_VALUE 1 + NUMERIC_MIN_VALUE 10 NUMERIC_MAX_VALUE 1048576 -@@ -5126,7 +5126,7 @@ +@@ -5254,7 +5254,7 @@ GLOBAL_VALUE_ORIGIN AUTO DEFAULT_VALUE 256 VARIABLE_SCOPE GLOBAL @@ -1281,7 +1272,7 @@ VARIABLE_COMMENT How many threads we should keep in a cache for reuse. These are freed after 5 minutes of idle time NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 16384 -@@ -5140,7 +5140,7 @@ +@@ -5268,7 +5268,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 10 VARIABLE_SCOPE GLOBAL @@ -1290,7 +1281,7 @@ VARIABLE_COMMENT Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.This variable has no effect, and is deprecated. It will be removed in a future release. NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 512 -@@ -5345,15 +5345,15 @@ +@@ -5473,15 +5473,15 @@ READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME TMP_DISK_TABLE_SIZE @@ -1310,7 +1301,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -5367,7 +5367,7 @@ +@@ -5495,7 +5495,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. Same as tmp_table_size. NUMERIC_MIN_VALUE 1024 @@ -1319,7 +1310,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -5381,7 +5381,7 @@ +@@ -5509,7 +5509,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Alias for tmp_memory_table_size. If an internal in-memory temporary table exceeds this size, MariaDB will automatically convert it to an on-disk MyISAM or Aria table. NUMERIC_MIN_VALUE 1024 @@ -1328,7 +1319,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -5392,7 +5392,7 @@ +@@ -5520,7 +5520,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 8192 VARIABLE_SCOPE SESSION @@ -1337,7 +1328,7 @@ VARIABLE_COMMENT Allocation block size for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -5406,7 +5406,7 @@ +@@ -5534,7 +5534,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 4096 VARIABLE_SCOPE SESSION @@ -1346,7 +1337,7 @@ VARIABLE_COMMENT Persistent buffer for transactions to be stored in binary log NUMERIC_MIN_VALUE 1024 NUMERIC_MAX_VALUE 134217728 -@@ -5504,7 +5504,7 @@ +@@ -5632,7 +5632,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE 28800 VARIABLE_SCOPE SESSION @@ -1355,7 +1346,7 @@ VARIABLE_COMMENT The number of seconds the server waits for activity on a connection before closing it NUMERIC_MIN_VALUE 1 NUMERIC_MAX_VALUE 31536000 -@@ -5609,7 +5609,7 @@ +@@ -5737,7 +5737,7 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME OPEN_FILES_LIMIT VARIABLE_SCOPE GLOBAL @@ -1364,7 +1355,7 @@ VARIABLE_COMMENT If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 or autoset then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of file descriptors NUMERIC_MIN_VALUE 0 NUMERIC_MAX_VALUE 4294967295 -@@ -5622,7 +5622,7 @@ +@@ -5750,7 +5750,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1373,7 +1364,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -5632,7 +5632,7 @@ +@@ -5760,7 +5760,7 @@ VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_COMMENT Sets the internal state of the RAND() generator for replication purposes NUMERIC_MIN_VALUE 0 @@ -1382,7 +1373,7 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO -@@ -5727,7 +5727,7 @@ +@@ -5855,7 +5855,7 @@ VARIABLE_NAME LOG_TC_SIZE GLOBAL_VALUE_ORIGIN AUTO VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 219b550d83e..631b75b7196 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -2966,6 +2966,34 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME OPTIMIZER_TRACE +SESSION_VALUE enabled=off +GLOBAL_VALUE enabled=off +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE enabled=off +VARIABLE_SCOPE SESSION +VARIABLE_TYPE FLAGSET +VARIABLE_COMMENT Controls tracing of the Optimizer: optimizer_trace=option=val[,option=val...], where option is one of {enabled} and val is one of {on, off, default} +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST enabled,default +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME OPTIMIZER_TRACE_MAX_MEM_SIZE +SESSION_VALUE 1048576 +GLOBAL_VALUE 1048576 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 1048576 +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT Maximum allowed size of an optimizer trace +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY SESSION_VALUE 4 GLOBAL_VALUE 4 diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index a22ce694805..69ca326c1fd 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -139,6 +139,7 @@ SET (SQL_SOURCE sql_sequence.cc sql_sequence.h ha_sequence.h sql_tvc.cc sql_tvc.h opt_split.cc + opt_trace.cc ${WSREP_SOURCES} table_cache.cc encryption.cc temporary_tables.cc proxy_protocol.cc backup.cc diff --git a/sql/handler.h b/sql/handler.h index dfb2333b24e..afe62123170 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -993,6 +993,7 @@ enum enum_schema_tables SCH_KEY_CACHES, SCH_KEY_COLUMN_USAGE, SCH_OPEN_TABLES, + SCH_OPT_TRACE, SCH_PARAMETERS, SCH_PARTITIONS, SCH_PLUGINS, diff --git a/sql/my_json_writer.cc b/sql/my_json_writer.cc index 9c4d63f9c4a..7ae0c58bd7d 100644 --- a/sql/my_json_writer.cc +++ b/sql/my_json_writer.cc @@ -219,19 +219,20 @@ void Json_writer::add_str(const String &str) add_str(str.ptr(), str.length()); } -Json_writer_object::Json_writer_object(Json_writer *writer):Json_writer_struct(writer) +Json_writer_object::Json_writer_object(THD *thd) : + Json_writer_struct(thd) { if (my_writer) my_writer->start_object(); } -Json_writer_object::Json_writer_object(Json_writer *writer, const char *str) - :Json_writer_struct(writer) +Json_writer_object::Json_writer_object(THD* thd, const char *str) + : Json_writer_struct(thd) { if (my_writer) my_writer->add_member(str).start_object(); - } + Json_writer_object::~Json_writer_object() { if (!closed && my_writer) @@ -239,14 +240,15 @@ Json_writer_object::~Json_writer_object() closed= TRUE; } -Json_writer_array::Json_writer_array(Json_writer *writer):Json_writer_struct(writer) +Json_writer_array::Json_writer_array(THD *thd) : + Json_writer_struct(thd) { if (my_writer) my_writer->start_array(); } -Json_writer_array::Json_writer_array(Json_writer *writer, const char *str) - :Json_writer_struct(writer) +Json_writer_array::Json_writer_array(THD *thd, const char *str) + :Json_writer_struct(thd) { if (my_writer) my_writer->add_member(str).start_array(); diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h index fcf853b0b62..4701cb4165b 100644 --- a/sql/my_json_writer.h +++ b/sql/my_json_writer.h @@ -100,6 +100,80 @@ public: }; +/* + Something that looks like class String, but has an internal limit of + how many bytes one can append to it. + + Bytes that were truncated due to the size limitation are counted. +*/ + +class String_with_limit +{ +public: + + String_with_limit() : size_limit(SIZE_MAX), truncated_len(0) + { + str.length(0); + } + + size_t get_truncated_bytes() const { return truncated_len; } + size_t get_size_limit() { return size_limit; } + + void set_size_limit(size_t limit_arg) + { + // Setting size limit to be shorter than length will not have the desired + // effect + DBUG_ASSERT(str.length() < size_limit); + size_limit= limit_arg; + } + + void append(const char *s, size_t size) + { + if (str.length() + size <= size_limit) + { + // Whole string can be added, just do it + str.append(s, size); + } + else + { + // We cannot add the whole string + if (str.length() < size_limit) + { + // But we can still add something + size_t bytes_to_add = size_limit - str.length(); + str.append(s, bytes_to_add); + truncated_len += size - bytes_to_add; + } + else + truncated_len += size; + } + } + + void append(const char *s) + { + append(s, strlen(s)); + } + + void append(char c) + { + if (str.length() + 1 > size_limit) + truncated_len++; + else + str.append(c); + } + + const String *get_string() { return &str; } + size_t length() { return str.length(); } +private: + String str; + + // str must not get longer than this many bytes. + size_t size_limit; + + // How many bytes were truncated from the string + size_t truncated_len; +}; + /* A class to write well-formed JSON documents. The documents are also formatted for human readability. @@ -116,7 +190,8 @@ public: void add_str(const char* val, size_t num_bytes); void add_str(const String &str); void add_str(Item *item); - void add_table_name(JOIN_TAB *tab); + void add_table_name(const JOIN_TAB *tab); + void add_table_name(const TABLE* table); void add_ll(longlong val); void add_size(longlong val); @@ -134,9 +209,18 @@ public: void end_object(); void end_array(); + /* + One can set a limit of how large a JSON document should be. + Writes beyond that size will be counted, but will not be collected. + */ + void set_size_limit(size_t mem_size) { output.set_size_limit(mem_size); } + + // psergey: return how many bytes would be required to store everything + size_t get_truncated_bytes() { return output.get_truncated_bytes(); } + Json_writer() : indent_level(0), document_start(true), element_started(false), - first_child(true) + first_child(true), allowed_mem_size(0) { fmt_helper.init(this); } @@ -151,22 +235,28 @@ private: bool element_started; bool first_child; + /* + True when we are using the optimizer trace + FALSE otherwise + */ + size_t allowed_mem_size; + Single_line_formatting_helper fmt_helper; void append_indent(); void start_element(); void start_sub_element(); - //const char *new_member_name; public: - String output; + String_with_limit output; }; /* A class to add values to Json_writer_object and Json_writer_array */ -class Json_value_context +class Json_value_helper { Json_writer* writer; - public: + +public: void init(Json_writer *my_writer) { writer= my_writer; } void add_str(const char* val) { @@ -219,11 +309,16 @@ class Json_value_context if (writer) writer->add_null(); } - void add_table_name(JOIN_TAB *tab) + void add_table_name(const JOIN_TAB *tab) { if (writer) writer->add_table_name(tab); } + void add_table_name(const TABLE* table) + { + if (writer) + writer->add_table_name(table); + } }; /* A common base for Json_writer_object and Json_writer_array */ @@ -231,17 +326,17 @@ class Json_writer_struct { protected: Json_writer* my_writer; - Json_value_context context; + Json_value_helper context; /* Tells when a json_writer_struct has been closed or not */ bool closed; public: - Json_writer_struct(Json_writer* writer) + explicit Json_writer_struct(THD *thd) { - my_writer= writer; - context.init(writer); + my_writer= thd->opt_trace.get_current_json(); + context.init(my_writer); closed= false; } }; @@ -249,9 +344,13 @@ public: /* RAII-based class to start/end writing a JSON object into the JSON document + + There is "ignore mode": one can initialize Json_writer_object with a NULL + Json_writer argument, and then all its calls will do nothing. This is used + by optimizer trace which can be enabled or disabled. */ -class Json_writer_object:public Json_writer_struct +class Json_writer_object : public Json_writer_struct { private: void add_member(const char *name) @@ -260,46 +359,49 @@ private: my_writer->add_member(name); } public: - Json_writer_object(Json_writer *w); - Json_writer_object(Json_writer *w, const char *str); + explicit Json_writer_object(THD *thd); + explicit Json_writer_object(THD *thd, const char *str); + Json_writer_object& add(const char *name, bool value) { + DBUG_ASSERT(!closed); add_member(name); context.add_bool(value); return *this; } - Json_writer_object& add(const char* name, uint value) + Json_writer_object& add(const char *name, ulonglong value) { + DBUG_ASSERT(!closed); add_member(name); - context.add_ll(value); - return *this; - } - Json_writer_object& add(const char* name, ha_rows value) - { - add_member(name); - context.add_ll(value); + context.add_ll(static_cast(value)); return *this; } Json_writer_object& add(const char *name, longlong value) { + DBUG_ASSERT(!closed); add_member(name); context.add_ll(value); return *this; } Json_writer_object& add(const char *name, double value) { + DBUG_ASSERT(!closed); add_member(name); context.add_double(value); return *this; } + #ifndef _WIN64 Json_writer_object& add(const char *name, size_t value) { + DBUG_ASSERT(!closed); add_member(name); - context.add_ll(value); + context.add_ll(static_cast(value)); return *this; } + #endif Json_writer_object& add(const char *name, const char *value) { + DBUG_ASSERT(!closed); add_member(name); context.add_str(value); return *this; @@ -310,38 +412,54 @@ public: context.add_str(value, num_bytes); return *this; } - Json_writer_object& add(const char *name, const String &value) - { - add_member(name); - context.add_str(value); - return *this; - } Json_writer_object& add(const char *name, LEX_CSTRING value) { + DBUG_ASSERT(!closed); add_member(name); context.add_str(value.str); return *this; } Json_writer_object& add(const char *name, Item *value) { + DBUG_ASSERT(!closed); add_member(name); context.add_str(value); return *this; } Json_writer_object& add_null(const char*name) { + DBUG_ASSERT(!closed); add_member(name); context.add_null(); return *this; } - Json_writer_object& add_table_name(JOIN_TAB *tab) + Json_writer_object& add_table_name(const JOIN_TAB *tab) { + DBUG_ASSERT(!closed); add_member("table"); context.add_table_name(tab); return *this; } + Json_writer_object& add_table_name(const TABLE *table) + { + DBUG_ASSERT(!closed); + add_member("table"); + context.add_table_name(table); + return *this; + } + Json_writer_object& add_select_number(uint select_number) + { + DBUG_ASSERT(!closed); + add_member("select_id"); + if (unlikely(select_number >= INT_MAX)) + context.add_str("fake"); + else + context.add_ll(static_cast(select_number)); + return *this; + } void end() { + DBUG_ASSERT(!closed); if (my_writer) my_writer->end_object(); closed= TRUE; @@ -352,83 +470,99 @@ public: /* RAII-based class to start/end writing a JSON array into the JSON document + + There is "ignore mode": one can initialize Json_writer_array with a NULL + Json_writer argument, and then all its calls will do nothing. This is used + by optimizer trace which can be enabled or disabled. */ -class Json_writer_array:public Json_writer_struct + +class Json_writer_array : public Json_writer_struct { public: - Json_writer_array(Json_writer *w); - Json_writer_array(Json_writer *w, const char *str); + Json_writer_array(THD *thd); + Json_writer_array(THD *thd, const char *str); void end() { + DBUG_ASSERT(!closed); if (my_writer) my_writer->end_array(); closed= TRUE; } + Json_writer_array& add(bool value) { + DBUG_ASSERT(!closed); context.add_bool(value); return *this; } - Json_writer_array& add(uint value) + Json_writer_array& add(ulonglong value) { - context.add_ll(value); - return *this; - } - Json_writer_array& add(ha_rows value) - { - context.add_ll(value); + DBUG_ASSERT(!closed); + context.add_ll(static_cast(value)); return *this; } Json_writer_array& add(longlong value) { + DBUG_ASSERT(!closed); context.add_ll(value); return *this; } Json_writer_array& add(double value) { + DBUG_ASSERT(!closed); context.add_double(value); return *this; } + #ifndef _WIN64 Json_writer_array& add(size_t value) { - context.add_ll(value); + DBUG_ASSERT(!closed); + context.add_ll(static_cast(value)); return *this; } + #endif Json_writer_array& add(const char *value) { + DBUG_ASSERT(!closed); context.add_str(value); return *this; } Json_writer_array& add(const char *value, size_t num_bytes) { + DBUG_ASSERT(!closed); context.add_str(value, num_bytes); return *this; } - Json_writer_array& add(const String &value) - { - context.add_str(value); - return *this; - } Json_writer_array& add(LEX_CSTRING value) { + DBUG_ASSERT(!closed); context.add_str(value.str); return *this; } Json_writer_array& add(Item *value) { + DBUG_ASSERT(!closed); context.add_str(value); return *this; } Json_writer_array& add_null() { + DBUG_ASSERT(!closed); context.add_null(); return *this; } - Json_writer_array& add_table_name(JOIN_TAB *tab) + Json_writer_array& add_table_name(const JOIN_TAB *tab) { + DBUG_ASSERT(!closed); context.add_table_name(tab); return *this; } + Json_writer_array& add_table_name(const TABLE *table) + { + DBUG_ASSERT(!closed); + context.add_table_name(table); + return *this; + } ~Json_writer_array(); }; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index eca51b54dab..c87a0595a7d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -119,6 +119,7 @@ #include "sql_select.h" #include "sql_statistics.h" #include "uniques.h" +#include "my_json_writer.h" #ifndef EXTRA_DEBUG #define test_rb_tree(A,B) {} @@ -429,6 +430,18 @@ static int and_range_trees(RANGE_OPT_PARAM *param, SEL_TREE *result); static bool remove_nonrange_trees(RANGE_OPT_PARAM *param, SEL_TREE *tree); +static void print_key_value(String *out, const KEY_PART_INFO *key_part, + const uchar *key); + +static void append_range_all_keyparts(Json_writer_array *range_trace, + String *range_string, + String *range_so_far, const SEL_ARG *keypart, + const KEY_PART_INFO *key_parts); + +static +void append_range(String *out, const KEY_PART_INFO *key_parts, + const uchar *min_key, const uchar *max_key, const uint flag); + /* SEL_IMERGE is a list of possible ways to do index merge, i.e. it is @@ -2191,6 +2204,14 @@ public: static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* Never called */ } virtual ~TABLE_READ_PLAN() {} /* Remove gcc warning */ + /** + Add basic info for this TABLE_READ_PLAN to the optimizer trace. + + @param param Parameters for range analysis of this table + @param trace_object The optimizer trace object the info is appended to + */ + virtual void trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const = 0; }; @@ -2232,8 +2253,34 @@ public: } DBUG_RETURN(quick); } + void trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const; }; +void TRP_RANGE::trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const +{ + DBUG_ASSERT(param->using_real_indexes); + const uint keynr_in_table = param->real_keynr[key_idx]; + + const KEY &cur_key = param->table->key_info[keynr_in_table]; + const KEY_PART_INFO *key_part = cur_key.key_part; + + trace_object->add("type", "range_scan") + .add("index", cur_key.name) + .add("rows", records); + + Json_writer_array trace_range(param->thd, "ranges"); + + // TRP_RANGE should not be created if there are no range intervals + DBUG_ASSERT(key); + + String range_info; + range_info.length(0); + range_info.set_charset(system_charset_info); + append_range_all_keyparts(&trace_range, NULL, &range_info, key, key_part); +} + /* Plan for QUICK_ROR_INTERSECT_SELECT scan. */ @@ -2251,9 +2298,12 @@ public: struct st_ror_scan_info *cpk_scan; /* Clustered PK scan, if there is one */ bool is_covering; /* TRUE if no row retrieval phase is necessary */ double index_scan_costs; /* SUM(cost(index_scan)) */ + void trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const; }; + /* Plan for QUICK_ROR_UNION_SELECT scan. QUICK_ROR_UNION_SELECT always retrieves full rows, so retrieve_full_rows @@ -2269,8 +2319,22 @@ public: MEM_ROOT *parent_alloc); TABLE_READ_PLAN **first_ror; /* array of ptrs to plans for merged scans */ TABLE_READ_PLAN **last_ror; /* end of the above array */ + void trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const; }; +void TRP_ROR_UNION::trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const +{ + THD *thd= param->thd; + trace_object->add("type", "index_roworder_union"); + Json_writer_array smth_trace(thd, "union_of"); + for (TABLE_READ_PLAN **current = first_ror; current != last_ror; current++) + { + Json_writer_object trp_info(thd); + (*current)->trace_basic_info(param, &trp_info); + } +} /* Plan for QUICK_INDEX_INTERSECT_SELECT scan. @@ -2288,9 +2352,25 @@ public: TRP_RANGE **range_scans; /* array of ptrs to plans of intersected scans */ TRP_RANGE **range_scans_end; /* end of the array */ /* keys whose scans are to be filtered by cpk conditions */ - key_map filtered_scans; + key_map filtered_scans; + void trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const; + }; +void TRP_INDEX_INTERSECT::trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const +{ + THD *thd= param->thd; + trace_object->add("type", "index_sort_intersect"); + Json_writer_array smth_trace(thd, "index_sort_intersect_of"); + for (TRP_RANGE **current = range_scans; current != range_scans_end; + current++) + { + Json_writer_object trp_info(thd); + (*current)->trace_basic_info(param, &trp_info); + } +} /* Plan for QUICK_INDEX_MERGE_SELECT scan. @@ -2307,8 +2387,22 @@ public: MEM_ROOT *parent_alloc); TRP_RANGE **range_scans; /* array of ptrs to plans of merged scans */ TRP_RANGE **range_scans_end; /* end of the array */ + void trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const; }; +void TRP_INDEX_MERGE::trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const +{ + THD *thd= param->thd; + trace_object->add("type", "index_merge"); + Json_writer_array smth_trace(thd, "index_merge_of"); + for (TRP_RANGE **current= range_scans; current != range_scans_end; current++) + { + Json_writer_object trp_info(thd); + (*current)->trace_basic_info(param, &trp_info); + } +} /* Plan for a QUICK_GROUP_MIN_MAX_SELECT scan. @@ -2360,9 +2454,51 @@ public: QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows, MEM_ROOT *parent_alloc); void use_index_scan() { is_index_scan= TRUE; } + void trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const; }; +void TRP_GROUP_MIN_MAX::trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const +{ + THD *thd= param->thd; + trace_object->add("type", "index_group").add("index", index_info->name); + + if (min_max_arg_part) + trace_object->add("group_attribute", min_max_arg_part->field->field_name); + else + trace_object->add_null("group_attribute"); + + trace_object->add("min_aggregate", have_min) + .add("max_aggregate", have_max) + .add("distinct_aggregate", have_agg_distinct) + .add("rows", records) + .add("cost", read_cost); + + const KEY_PART_INFO *key_part = index_info->key_part; + { + Json_writer_array trace_keyparts(thd, "key_parts_used_for_access"); + for (uint partno = 0; partno < used_key_parts; partno++) + { + const KEY_PART_INFO *cur_key_part = key_part + partno; + trace_keyparts.add(cur_key_part->field->field_name); + } + } + + Json_writer_array trace_range(thd, "ranges"); + + // can have group quick without ranges + if (index_tree) + { + String range_info; + range_info.set_charset(system_charset_info); + append_range_all_keyparts(&trace_range, NULL, &range_info, index_tree, + key_part); + } +} + + typedef struct st_index_scan_info { uint idx; /* # of used key in param->keys */ @@ -2538,6 +2674,17 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, DBUG_PRINT("info",("Time to scan table: %g", read_time)); + Json_writer_object table_records(thd); + if (head->reginfo.join_tab) + table_records.add_table_name(head->reginfo.join_tab); + else + table_records.add_table_name(head); + Json_writer_object trace_range(thd, "range_analysis"); + { + Json_writer_object table_rec(thd, "table_scan"); + table_rec.add("rows", records).add("cost", read_time); + } + keys_to_use.intersect(head->keys_in_use_for_query); if (!keys_to_use.is_clear_all()) { @@ -2591,19 +2738,33 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, */ key_info= head->key_info; uint max_key_len= 0; + + Json_writer_array trace_idx(thd, "potential_range_indexes"); + for (idx=0 ; idx < head->s->keys ; idx++, key_info++) { + Json_writer_object trace_idx_details(thd); + trace_idx_details.add("index", key_info->name); KEY_PART_INFO *key_part_info; uint n_key_parts= head->actual_n_key_parts(key_info); if (!keys_to_use.is_set(idx)) - continue; + { + trace_idx_details.add("usable", false) + .add("cause", "not applicable"); + continue; + } if (key_info->flags & HA_FULLTEXT) - continue; // ToDo: ft-keys in non-ft ranges, if possible SerG + { + trace_idx_details.add("usable", false).add("cause", "fulltext"); + continue; // ToDo: ft-keys in non-ft ranges, if possible SerG + } + trace_idx_details.add("usable", true); param.key[param.keys]=key_parts; key_part_info= key_info->key_part; uint cur_key_len= 0; + Json_writer_array trace_keypart(thd, "key_parts"); for (uint part= 0 ; part < n_key_parts ; part++, key_parts++, key_part_info++) { @@ -2618,11 +2779,14 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, (key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW; /* Only HA_PART_KEY_SEG is used */ key_parts->flag= (uint8) key_part_info->key_part_flag; + trace_keypart.add(key_parts->field->field_name); } param.real_keynr[param.keys++]=idx; if (cur_key_len > max_key_len) max_key_len= cur_key_len; } + trace_idx.end(); + param.key_parts_end=key_parts; param.alloced_sel_args= 0; @@ -2644,8 +2808,18 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, (double) records / TIME_FOR_COMPARE; DBUG_PRINT("info", ("'all'+'using index' scan will be using key %d, " "read time %g", key_for_use, key_read_time)); + + Json_writer_object trace_cov(thd, "best_covering_index_scan"); + bool chosen= FALSE; if (key_read_time < read_time) + { read_time= key_read_time; + chosen= TRUE; + } + trace_cov.add("index", head->key_info[key_for_use].name) + .add("cost", key_read_time).add("chosen", chosen); + if (!chosen) + trace_cov.add("cause", "cost"); } TABLE_READ_PLAN *best_trp= NULL; @@ -2654,12 +2828,18 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, if (cond) { - if ((tree= cond->get_mm_tree(¶m, &cond))) + { + Json_writer_array trace_range_summary(thd, + "setup_range_conditions"); + tree= cond->get_mm_tree(¶m, &cond); + } + if (tree) { if (tree->type == SEL_TREE::IMPOSSIBLE) { records=0L; /* Return -1 from this function. */ read_time= (double) HA_POS_ERROR; + trace_range.add("impossible_range", true); goto free_mem; } /* @@ -2667,7 +2847,10 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, can construct a group-min-max quick select */ if (tree->type != SEL_TREE::KEY && tree->type != SEL_TREE::KEY_SMALLER) + { + trace_range.add("range_scan_possible", false); tree= NULL; + } } } @@ -2680,11 +2863,19 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, { param.table->quick_condition_rows= MY_MIN(group_trp->records, head->stat_records()); + Json_writer_object grp_summary(thd, "best_group_range_summary"); + + if (unlikely(thd->trace_started())) + group_trp->trace_basic_info(¶m, &grp_summary); + if (group_trp->read_cost < best_read_time) { + grp_summary.add("chosen", true); best_trp= group_trp; best_read_time= best_trp->read_cost; } + else + grp_summary.add("chosen", false).add("cause", "cost"); } if (tree) @@ -2697,7 +2888,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, TRP_ROR_INTERSECT *rori_trp; TRP_INDEX_INTERSECT *intersect_trp; bool can_build_covering= FALSE; - + Json_writer_object trace_range(thd, "analyzing_range_alternatives"); + remove_nonrange_trees(¶m, tree); /* Get best 'range' plan and prepare data for making other plans */ @@ -2764,6 +2956,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, DBUG_PRINT("info",("No range reads possible," " trying to construct index_merge")); List_iterator_fast it(tree->merges); + Json_writer_array trace_idx_merge(thd, "analyzing_index_merge_union"); while ((imerge= it++)) { new_conj_trp= get_best_disjunct_quick(¶m, imerge, best_read_time); @@ -2798,6 +2991,19 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, possible_keys= param.possible_keys; free_mem: + if (unlikely(quick && best_trp && thd->trace_started())) + { + Json_writer_object trace_range_summary(thd, + "chosen_range_access_summary"); + { + Json_writer_object trace_range_plan(thd, "range_access_plan"); + best_trp->trace_basic_info(¶m, &trace_range_plan); + } + trace_range_summary.add("rows_for_plan", quick->records) + .add("cost_for_plan", quick->read_time) + .add("chosen", true); + } + free_root(&alloc,MYF(0)); // Return memory & allocator thd->mem_root= param.old_root; thd->no_errors=0; @@ -3060,6 +3266,9 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) estimate sources. */ + Json_writer_object trace_wrapper(thd); + Json_writer_array selectivity_for_indexes(thd, "selectivity_for_indexes"); + for (keynr= 0; keynr < table->s->keys; keynr++) { if (table->quick_keys.is_set(keynr)) @@ -3109,6 +3318,10 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) not yet been accounted for. */ table->cond_selectivity*= quick_cond_selectivity; + Json_writer_object selectivity_for_index(thd); + selectivity_for_index.add("index_name", key_info->name) + .add("selectivity_from_index", + quick_cond_selectivity); if (i != used_key_parts) { /* @@ -3128,7 +3341,9 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) */ selectivity_mult= ((double)(i+1)) / i; } - table->cond_selectivity*= selectivity_mult; + table->cond_selectivity*= selectivity_mult; + selectivity_for_index.add("selectivity_multiplier", + selectivity_mult); } /* We need to set selectivity for fields supported by indexes. @@ -3149,12 +3364,14 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) } } } + selectivity_for_indexes.end(); /* Second step: calculate the selectivity of the range conditions not supported by any index and selectivity of the range condition over the fields whose selectivity has not been set yet. */ + Json_writer_array selectivity_for_columns(thd, "selectivity_for_columns"); if (thd->variables.optimizer_use_condition_selectivity > 2 && !bitmap_is_clear_all(used_fields) && @@ -3214,17 +3431,25 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) SEL_ARG *key= tree->keys[idx]; if (key) { + Json_writer_object selectivity_for_column(thd); + selectivity_for_column.add("column_name", key->field->field_name); if (key->type == SEL_ARG::IMPOSSIBLE) - { + { rows= 0; table->reginfo.impossible_range= 1; + selectivity_for_column.add("selectivity_from_histograms", rows); + selectivity_for_column.add("cause", "impossible range"); goto free_alloc; } else { rows= records_in_column_ranges(¶m, idx, key); if (rows != DBL_MAX) + { key->field->cond_selectivity= rows/table_records; + selectivity_for_column.add("selectivity_from_histograms", + key->field->cond_selectivity); + } } } } @@ -4791,6 +5016,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, ha_rows roru_total_records; double roru_intersect_part= 1.0; size_t n_child_scans; + THD *thd= param->thd; DBUG_ENTER("get_best_disjunct_quick"); DBUG_PRINT("info", ("Full table scan cost: %g", read_time)); @@ -4816,6 +5042,8 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, sizeof(TRP_RANGE*)* n_child_scans))) DBUG_RETURN(NULL); + Json_writer_object trace_best_disjunct(thd); + Json_writer_array to_merge(thd, "indexes_to_merge"); /* Collect best 'range' scan for each of disjuncts, and, while doing so, analyze possibility of ROR scans. Also calculate some values needed by @@ -4827,6 +5055,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, { DBUG_EXECUTE("info", print_sel_tree(param, *ptree, &(*ptree)->keys_map, "tree in SEL_IMERGE");); + Json_writer_object trace_idx(thd); if (!(*cur_child= get_key_scans_params(param, *ptree, TRUE, FALSE, read_time))) { /* @@ -4838,8 +5067,11 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, imerge_too_expensive= TRUE; } if (imerge_too_expensive) + { + trace_idx.add("chosen", false).add("cause", "cost"); continue; - + } + const uint keynr_in_table = param->real_keynr[(*cur_child)->key_idx]; imerge_cost += (*cur_child)->read_cost; all_scans_ror_able &= ((*ptree)->n_ror_scans > 0); all_scans_rors &= (*cur_child)->is_ror; @@ -4852,9 +5084,16 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, } else non_cpk_scan_records += (*cur_child)->records; + trace_idx.add("index_to_merge", + param->table->key_info[keynr_in_table].name) + .add("cumulated_cost", imerge_cost); } + to_merge.end(); + DBUG_PRINT("info", ("index_merge scans cost %g", imerge_cost)); + trace_best_disjunct.add("cost_of_reading_ranges", imerge_cost); + if (imerge_too_expensive || (imerge_cost > read_time) || ((non_cpk_scan_records+cpk_scan_records >= param->table->stat_records()) && @@ -4866,6 +5105,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, */ DBUG_PRINT("info", ("Sum of index_merge scans is more expensive than " "full table scan, bailing out")); + trace_best_disjunct.add("chosen", false).add("cause", "cost"); DBUG_RETURN(NULL); } @@ -4878,6 +5118,9 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_UNION)) { roru_read_plans= (TABLE_READ_PLAN**)range_scans; + trace_best_disjunct.add("use_roworder_union", true) + .add("cause", + "always cheaper than non roworder retrieval"); goto skip_to_ror_scan; } @@ -4887,16 +5130,26 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, Add one ROWID comparison for each row retrieved on non-CPK scan. (it is done in QUICK_RANGE_SELECT::row_in_ranges) */ - imerge_cost += non_cpk_scan_records / TIME_FOR_COMPARE_ROWID; + double rid_comp_cost= static_cast(non_cpk_scan_records) / + TIME_FOR_COMPARE_ROWID; + imerge_cost += rid_comp_cost; + trace_best_disjunct.add("cost_of_mapping_rowid_in_non_clustered_pk_scan", + rid_comp_cost); } /* Calculate cost(rowid_to_row_scan) */ - imerge_cost += get_sweep_read_cost(param, non_cpk_scan_records); + { + double sweep_cost= get_sweep_read_cost(param, non_cpk_scan_records); + imerge_cost += sweep_cost; + trace_best_disjunct.add("cost_sort_rowid_and_read_disk", sweep_cost); + } DBUG_PRINT("info",("index_merge cost with rowid-to-row scan: %g", imerge_cost)); if (imerge_cost > read_time || !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION)) { + trace_best_disjunct.add("use_roworder_index_merge", true); + trace_best_disjunct.add("cause", "cost"); goto build_ror_index_merge; } @@ -4913,12 +5166,18 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, param->imerge_cost_buff_size= unique_calc_buff_size; } - imerge_cost += - Unique::get_use_cost(param->imerge_cost_buff, (uint)non_cpk_scan_records, - param->table->file->ref_length, - (size_t)param->thd->variables.sortbuff_size, - TIME_FOR_COMPARE_ROWID, - FALSE, NULL); + { + const double dup_removal_cost = Unique::get_use_cost( + param->imerge_cost_buff, (uint)non_cpk_scan_records, + param->table->file->ref_length, + (size_t)param->thd->variables.sortbuff_size, + TIME_FOR_COMPARE_ROWID, + FALSE, NULL); + imerge_cost+= dup_removal_cost; + trace_best_disjunct.add("cost_duplicate_removal", dup_removal_cost) + .add("total_cost", imerge_cost); + } + DBUG_PRINT("info",("index_merge total cost: %g (wanted: less then %g)", imerge_cost, read_time)); if (imerge_cost < read_time) @@ -4961,11 +5220,16 @@ skip_to_ror_scan: roru_total_records= 0; cur_roru_plan= roru_read_plans; + Json_writer_array trace_analyze_ror(thd, "analyzing_roworder_scans"); + /* Find 'best' ROR scan for each of trees in disjunction */ for (ptree= imerge->trees, cur_child= range_scans; ptree != imerge->trees_next; ptree++, cur_child++, cur_roru_plan++) { + Json_writer_object trp_info(thd); + if (unlikely(thd->trace_started())) + (*cur_child)->trace_basic_info(param, &trp_info); /* Assume the best ROR scan is the one that has cheapest full-row-retrieval scan cost. @@ -5001,7 +5265,7 @@ skip_to_ror_scan: roru_intersect_part *= (*cur_roru_plan)->records / param->table->stat_records(); } - + trace_analyze_ror.end(); /* rows to retrieve= SUM(rows_in_scan_i) - table_rows * PROD(rows_in_scan_i / table_rows). @@ -5027,11 +5291,14 @@ skip_to_ror_scan: DBUG_PRINT("info", ("ROR-union: cost %g, %zu members", roru_total_cost, n_child_scans)); + trace_best_disjunct.add("index_roworder_union_cost", roru_total_cost) + .add("members", n_child_scans); TRP_ROR_UNION* roru; if (roru_total_cost < read_time) { if ((roru= new (param->mem_root) TRP_ROR_UNION)) { + trace_best_disjunct.add("chosen", true); roru->first_ror= roru_read_plans; roru->last_ror= roru_read_plans + n_child_scans; roru->read_cost= roru_total_cost; @@ -5039,7 +5306,9 @@ skip_to_ror_scan: DBUG_RETURN(roru); } } - DBUG_RETURN(imerge_trp); + else + trace_best_disjunct.add("chosen", false); + DBUG_RETURN(imerge_trp); } @@ -5300,6 +5569,15 @@ ha_rows get_table_cardinality_for_index_intersect(TABLE *table) } } +static +void print_keyparts(THD *thd, KEY *key, uint key_parts) +{ + KEY_PART_INFO *part= key->key_part; + Json_writer_array keyparts= Json_writer_array(thd, "keyparts"); + for(uint i= 0; i < key_parts; i++, part++) + keyparts.add(part->field->field_name); +} + static ha_rows records_in_index_intersect_extension(PARTIAL_INDEX_INTERSECT_INFO *curr, @@ -5352,8 +5630,9 @@ bool prepare_search_best_index_intersect(PARAM *param, INDEX_SCAN_INFO *cpk_scan= NULL; TABLE *table= param->table; uint n_index_scans= (uint)(tree->index_scans_end - tree->index_scans); + THD *thd= param->thd; - if (!n_index_scans) + if (n_index_scans <= 1) return 1; bzero(init, sizeof(*init)); @@ -5370,9 +5649,6 @@ bool prepare_search_best_index_intersect(PARAM *param, common->table_cardinality= get_table_cardinality_for_index_intersect(table); - if (n_index_scans <= 1) - return TRUE; - if (table->file->primary_key_is_clustered()) { INDEX_SCAN_INFO **index_scan_end; @@ -5397,23 +5673,38 @@ bool prepare_search_best_index_intersect(PARAM *param, bzero(common->search_scans, sizeof(INDEX_SCAN_INFO *) * i); INDEX_SCAN_INFO **selected_index_scans= common->search_scans; - + Json_writer_array potential_idx_scans(thd, "potential_index_scans"); for (i=0, index_scan= tree->index_scans; i < n_index_scans; i++, index_scan++) { + Json_writer_object idx_scan(thd); uint used_key_parts= (*index_scan)->used_key_parts; KEY *key_info= (*index_scan)->key_info; + idx_scan.add("index", key_info->name); if (*index_scan == cpk_scan) + { + idx_scan.add("chosen", "false") + .add("cause", "clustered index used for filtering"); continue; + } if (cpk_scan && cpk_scan->used_key_parts >= used_key_parts && same_index_prefix(cpk_scan->key_info, key_info, used_key_parts)) + { + idx_scan.add("chosen", "false") + .add("cause", "clustered index used for filtering"); continue; + } cost= table->file->keyread_time((*index_scan)->keynr, (*index_scan)->range_count, (*index_scan)->records); + idx_scan.add("cost", cost); if (cost >= cutoff_cost) + { + idx_scan.add("chosen", false); + idx_scan.add("cause", "cost"); continue; + } for (scan_ptr= selected_index_scans; *scan_ptr ; scan_ptr++) { @@ -5430,10 +5721,20 @@ bool prepare_search_best_index_intersect(PARAM *param, } if (!*scan_ptr || cost < (*scan_ptr)->index_read_cost) { + idx_scan.add("chosen", true); + if (!*scan_ptr) + idx_scan.add("cause", "first occurence of index prefix"); + else + idx_scan.add("cause", "better cost for same idx prefix"); *scan_ptr= *index_scan; (*scan_ptr)->index_read_cost= cost; } - } + else + { + idx_scan.add("chosen", false).add("cause", "cost"); + } + } + potential_idx_scans.end(); ha_rows records_in_scans= 0; @@ -5443,6 +5744,7 @@ bool prepare_search_best_index_intersect(PARAM *param, return TRUE; records_in_scans+= (*scan_ptr)->records; } + n_search_scans= i; if (cpk_scan && create_fields_bitmap(param, &cpk_scan->used_fields)) @@ -5472,6 +5774,7 @@ bool prepare_search_best_index_intersect(PARAM *param, my_qsort(selected_index_scans, n_search_scans, sizeof(INDEX_SCAN_INFO *), (qsort_cmp) cmp_intersect_index_scan); + Json_writer_array selected_idx_scans(thd, "selected_index_scans"); if (cpk_scan) { PARTIAL_INDEX_INTERSECT_INFO curr; @@ -5484,16 +5787,36 @@ bool prepare_search_best_index_intersect(PARAM *param, curr.length= 1; for (scan_ptr=selected_index_scans; *scan_ptr; scan_ptr++) { + KEY *key_info= (*scan_ptr)->key_info; ha_rows scan_records= (*scan_ptr)->records; ha_rows records= records_in_index_intersect_extension(&curr, *scan_ptr); (*scan_ptr)->filtered_out= records >= scan_records ? - 0 : scan_records-records; + 0 : scan_records-records; + if (thd->trace_started()) + { + Json_writer_object selected_idx(thd); + selected_idx.add("index", key_info->name); + print_keyparts(thd, key_info, (*scan_ptr)->used_key_parts); + selected_idx.add("records", (*scan_ptr)->records) + .add("filtered_records", (*scan_ptr)->filtered_out); + } } } else { for (scan_ptr=selected_index_scans; *scan_ptr; scan_ptr++) + { + KEY *key_info= (*scan_ptr)->key_info; (*scan_ptr)->filtered_out= 0; + if (thd->trace_started()) + { + Json_writer_object selected_idx(thd); + selected_idx.add("index", key_info->name); + print_keyparts(thd, key_info, (*scan_ptr)->used_key_parts); + selected_idx.add("records", (*scan_ptr)->records) + .add("filtered_records", (*scan_ptr)->filtered_out); + } + } } return FALSE; @@ -5950,10 +6273,12 @@ TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree, PARTIAL_INDEX_INTERSECT_INFO init; TRP_INDEX_INTERSECT *intersect_trp= NULL; TABLE *table= param->table; - + THD *thd= param->thd; DBUG_ENTER("get_best_index_intersect"); + Json_writer_object trace_idx_interect(thd, "analyzing_sort_intersect"); + if (prepare_search_best_index_intersect(param, tree, &common, &init, read_time)) DBUG_RETURN(NULL); @@ -6015,11 +6340,15 @@ TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree, if ((intersect_trp= new (param->mem_root)TRP_INDEX_INTERSECT)) { + intersect_trp->read_cost= common.best_cost; intersect_trp->records= common.best_records; intersect_trp->range_scans= range_scans; intersect_trp->range_scans_end= cur_range; intersect_trp->filtered_scans= common.filtered_scans; + trace_idx_interect.add("rows", intersect_trp->records) + .add("cost", intersect_trp->read_cost) + .add("chosen",true); } DBUG_RETURN(intersect_trp); } @@ -6029,6 +6358,46 @@ typedef struct st_ror_scan_info : INDEX_SCAN_INFO { } ROR_SCAN_INFO; +void TRP_ROR_INTERSECT::trace_basic_info(const PARAM *param, + Json_writer_object *trace_object) const +{ + THD *thd= param->thd; + trace_object->add("type", "index_roworder_intersect"); + trace_object->add("rows", records); + trace_object->add("cost", read_cost); + trace_object->add("covering", is_covering); + trace_object->add("clustered_pk_scan", cpk_scan != NULL); + + Json_writer_array smth_trace(thd, "intersect_of"); + for (ROR_SCAN_INFO **cur_scan = first_scan; cur_scan != last_scan; + cur_scan++) + { + const KEY &cur_key = param->table->key_info[(*cur_scan)->keynr]; + const KEY_PART_INFO *key_part = cur_key.key_part; + + Json_writer_object trace_isect_idx(thd); + trace_isect_idx.add("type", "range_scan"); + trace_isect_idx.add("index", cur_key.name); + trace_isect_idx.add("rows", (*cur_scan)->records); + + Json_writer_array trace_range(thd, "ranges"); + for (const SEL_ARG *current = (*cur_scan)->sel_arg->first(); current; + current = current->next) + { + String range_info; + range_info.set_charset(system_charset_info); + for (const SEL_ARG *part = current; part; + part = part->next_key_part ? part->next_key_part : nullptr) + { + const KEY_PART_INFO *cur_key_part = key_part + part->part; + append_range(&range_info, cur_key_part, part->min_value, + part->max_value, part->min_flag | part->max_flag); + } + trace_range.add(range_info.ptr(), range_info.length()); + } + } +} + /* Create ROR_SCAN_INFO* structure with a single ROR scan on index idx using @@ -6414,7 +6783,9 @@ static double ror_scan_selectivity(const ROR_INTERSECT_INFO *info, */ static bool ror_intersect_add(ROR_INTERSECT_INFO *info, - ROR_SCAN_INFO* ror_scan, bool is_cpk_scan) + ROR_SCAN_INFO* ror_scan, + Json_writer_object *trace_costs, + bool is_cpk_scan) { double selectivity_mult= 1.0; @@ -6441,13 +6812,16 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info, each record of every scan. Assuming 1/TIME_FOR_COMPARE_ROWID per check this gives us: */ - info->index_scan_costs += rows2double(info->index_records) / + const double idx_cost= rows2double(info->index_records) / TIME_FOR_COMPARE_ROWID; + info->index_scan_costs += idx_cost; + trace_costs->add("index_scan_cost", idx_cost); } else { info->index_records += info->param->quick_rows[ror_scan->keynr]; info->index_scan_costs += ror_scan->index_read_cost; + trace_costs->add("index_scan_cost", ror_scan->index_read_cost); bitmap_union(&info->covered_fields, &ror_scan->covered_fields); if (!info->is_covering && bitmap_is_subset(&info->param->needed_fields, &info->covered_fields)) @@ -6458,13 +6832,19 @@ static bool ror_intersect_add(ROR_INTERSECT_INFO *info, } info->total_cost= info->index_scan_costs; + trace_costs->add("cumulateed_index_scan_cost", info->index_scan_costs); DBUG_PRINT("info", ("info->total_cost: %g", info->total_cost)); if (!info->is_covering) { - info->total_cost += - get_sweep_read_cost(info->param, double2rows(info->out_rows)); + double sweep_cost= get_sweep_read_cost(info->param, + double2rows(info->out_rows)); + info->total_cost += sweep_cost; + trace_costs->add("disk_sweep_cost", sweep_cost); DBUG_PRINT("info", ("info->total_cost= %g", info->total_cost)); } + else + trace_costs->add("disk_sweep_cost", static_cast(0)); + DBUG_PRINT("info", ("New out_rows: %g", info->out_rows)); DBUG_PRINT("info", ("New cost: %g, %scovering", info->total_cost, info->is_covering?"" : "non-")); @@ -6544,10 +6924,16 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, uint idx; double min_cost= DBL_MAX; DBUG_ENTER("get_best_ror_intersect"); + THD *thd= param->thd; + Json_writer_object trace_ror(thd, "analyzing_roworder_intersect"); if ((tree->n_ror_scans < 2) || !param->table->stat_records() || !optimizer_flag(param->thd, OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT)) - DBUG_RETURN(NULL); + { + if (tree->n_ror_scans < 2) + trace_ror.add("cause", "too few roworder scans"); + DBUG_RETURN(NULL); + } /* Step1: Collect ROR-able SEL_ARGs and create ROR_SCAN_INFO for each of @@ -6622,15 +7008,27 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, ROR_SCAN_INFO **intersect_scans_best; cur_ror_scan= tree->ror_scans; intersect_scans_best= intersect_scans; + Json_writer_array trace_isect_idx(thd, "intersecting_indexes"); while (cur_ror_scan != tree->ror_scans_end && !intersect->is_covering) { + Json_writer_object trace_idx(thd); + trace_idx.add("index", + param->table->key_info[(*cur_ror_scan)->keynr].name); + /* S= S + first(R); R= R - first(R); */ - if (!ror_intersect_add(intersect, *cur_ror_scan, FALSE)) + if (!ror_intersect_add(intersect, *cur_ror_scan, &trace_idx, FALSE)) { + trace_idx.add("usable", false) + .add("cause", "does not reduce cost of intersect"); cur_ror_scan++; continue; } + trace_idx.add("cumulative_total_cost", intersect->total_cost) + .add("usable", true) + .add("matching_rows_now", intersect->out_rows) + .add("intersect_covering_with_this_index", intersect->is_covering); + *(intersect_scans_end++)= *(cur_ror_scan++); if (intersect->total_cost < min_cost) @@ -6639,12 +7037,21 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, ror_intersect_cpy(intersect_best, intersect); intersect_scans_best= intersect_scans_end; min_cost = intersect->total_cost; + trace_idx.add("chosen", true); + } + else + { + trace_idx.add("chosen", false) + .add("cause", "does not reduce cost"); } } + trace_isect_idx.end(); if (intersect_scans_best == intersect_scans) { DBUG_PRINT("info", ("None of scans increase selectivity")); + trace_ror.add("chosen", false) + .add("cause","does not increase selectivity"); DBUG_RETURN(NULL); } @@ -6662,16 +7069,31 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, Check if we should add a CPK scan. If the obtained ROR-intersection is covering, it doesn't make sense to add CPK scan. */ + Json_writer_object trace_cpk(thd, "clustered_pk"); if (cpk_scan && !intersect->is_covering) { - if (ror_intersect_add(intersect, cpk_scan, TRUE) && + if (ror_intersect_add(intersect, cpk_scan, &trace_cpk, TRUE) && (intersect->total_cost < min_cost)) + { + trace_cpk.add("clustered_pk_scan_added_to_intersect", true) + .add("cumulated_cost", intersect->total_cost); intersect_best= intersect; //just set pointer here + } else + { + trace_cpk.add("clustered_pk_added_to_intersect", false) + .add("cause", "cost"); cpk_scan= 0; // Don't use cpk_scan + } } else + { + trace_cpk.add("clustered_pk_added_to_intersect", false) + .add("cause", cpk_scan ? "roworder is covering" + : "no clustered pk index"); cpk_scan= 0; // Don't use cpk_scan + } + trace_cpk.end(); /* Ok, return ROR-intersect plan if we have found one */ TRP_ROR_INTERSECT *trp= NULL; @@ -6698,6 +7120,17 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, DBUG_PRINT("info", ("Returning non-covering ROR-intersect plan:" "cost %g, records %lu", trp->read_cost, (ulong) trp->records)); + trace_ror.add("rows", trp->records) + .add("cost", trp->read_cost) + .add("covering", trp->is_covering) + .add("chosen", true); + } + else + { + trace_ror.add("chosen", false) + .add("cause", (read_time > min_cost) + ? "too few indexes to merge" + : "cost"); } DBUG_RETURN(trp); } @@ -6885,6 +7318,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, UNINIT_VAR(best_buf_size); /* protected by key_to_read */ TRP_RANGE* read_plan= NULL; DBUG_ENTER("get_key_scans_params"); + THD *thd= param->thd; /* Note that there may be trees that have type SEL_TREE::KEY but contain no key reads at all, e.g. tree for expression "key1 is not null" where key1 @@ -6892,6 +7326,8 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, */ DBUG_EXECUTE("info", print_sel_tree(param, tree, &tree->keys_map, "tree scans");); + Json_writer_array range_scan_alt(thd, "range_scan_alternatives"); + tree->ror_scans_map.clear_all(); tree->n_ror_scans= 0; tree->index_scans= 0; @@ -6920,6 +7356,9 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, bool read_index_only= index_read_must_be_used ? TRUE : (bool) param->table->covering_keys.is_set(keynr); + Json_writer_object trace_idx(thd); + trace_idx.add("index", param->table->key_info[keynr].name); + found_records= check_quick_select(param, idx, read_index_only, key, update_tbl_stats, &mrr_flags, &buf_size, &cost); @@ -6928,6 +7367,14 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, (index_scan= (INDEX_SCAN_INFO *)alloc_root(param->mem_root, sizeof(INDEX_SCAN_INFO)))) { + Json_writer_array trace_range(thd, "ranges"); + + const KEY &cur_key = param->table->key_info[keynr]; + const KEY_PART_INFO *key_part = cur_key.key_part; + + String range_info; + range_info.set_charset(system_charset_info); + index_scan->idx= idx; index_scan->keynr= keynr; index_scan->key_info= ¶m->table->key_info[keynr]; @@ -6936,6 +7383,17 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, index_scan->records= found_records; index_scan->sel_arg= key; *tree->index_scans_end++= index_scan; + + if (unlikely(thd->trace_started())) + append_range_all_keyparts(&trace_range, NULL, &range_info, key, + key_part); + trace_range.end(); + + trace_idx.add("rowid_ordered", param->is_ror_scan) + .add("using_mrr", !(mrr_flags & HA_MRR_USE_DEFAULT_IMPL)) + .add("index_only", read_index_only) + .add("rows", found_records) + .add("cost", cost.total_cost()); } if ((found_records != HA_POS_ERROR) && param->is_ror_scan) { @@ -6951,6 +7409,18 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, best_idx= idx; best_mrr_flags= mrr_flags; best_buf_size= buf_size; + trace_idx.add("chosen", true); + } + else + { + trace_idx.add("chosen", false); + if (found_records == HA_POS_ERROR) + if (key->type == SEL_ARG::Type::MAYBE_KEY) + trace_idx.add("cause", "depends on unread values"); + else + trace_idx.add("cause", "unknown"); + else + trace_idx.add("cause", "cost"); } } } @@ -7055,10 +7525,11 @@ QUICK_SELECT_I *TRP_ROR_INTERSECT::make_quick(PARAM *param, "creating ROR-intersect", first_scan, last_scan);); alloc= parent_alloc? parent_alloc: &quick_intrsect->alloc; - for (; first_scan != last_scan;++first_scan) + for (ROR_SCAN_INFO **curr_scan= first_scan; curr_scan != last_scan; + ++curr_scan) { - if (!(quick= get_quick_select(param, (*first_scan)->idx, - (*first_scan)->sel_arg, + if (!(quick= get_quick_select(param, (*curr_scan)->idx, + (*curr_scan)->sel_arg, HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED, 0, alloc)) || quick_intrsect->push_quick_back(alloc, quick)) @@ -12584,16 +13055,27 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) DBUG_ENTER("get_best_group_min_max"); + Json_writer_object trace_group(thd, "group_index_range"); + const char* cause= NULL; + /* Perform few 'cheap' tests whether this access method is applicable. */ - if (!join) - DBUG_RETURN(NULL); /* This is not a select statement. */ - if ((join->table_count != 1) || /* The query must reference one table. */ - (join->select_lex->olap == ROLLUP_TYPE)) /* Check (B3) for ROLLUP */ + if (!join) /* This is not a select statement. */ + cause= "no join"; + else if (join->table_count != 1) /* The query must reference one table. */ + cause= "not single_table"; + else if (join->select_lex->olap == ROLLUP_TYPE) /* Check (B3) for ROLLUP */ + cause= "rollup"; + else if (table->s->keys == 0) /* There are no indexes to use. */ + cause= "no index"; + else if (join->conds && join->conds->used_tables() + & OUTER_REF_TABLE_BIT) /* Cannot execute with correlated conditions. */ + cause= "correlated conditions"; + + if (cause) + { + trace_group.add("chosen", false).add("cause", cause); DBUG_RETURN(NULL); - if (table->s->keys == 0) /* There are no indexes to use. */ - DBUG_RETURN(NULL); - if (join->conds && join->conds->used_tables() & OUTER_REF_TABLE_BIT) - DBUG_RETURN(NULL); /* Cannot execute with correlated conditions. */ + } /* Check (SA1,SA4) and store the only MIN/MAX argument - the C attribute.*/ List_iterator select_items_it(join->fields_list); @@ -12602,7 +13084,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) if ((!join->group_list) && /* Neither GROUP BY nor a DISTINCT query. */ (!join->select_distinct) && !is_agg_distinct) + { + trace_group.add("chosen", false).add("cause","no group by or distinct"); DBUG_RETURN(NULL); + } /* Analyze the query in more detail. */ if (join->sum_funcs[0]) @@ -12621,7 +13106,11 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) min_max_item->sum_func() == Item_sum::AVG_DISTINCT_FUNC)) continue; else + { + trace_group.add("chosen", false) + .add("cause", "not applicable aggregate function"); DBUG_RETURN(NULL); + } /* The argument of MIN/MAX. */ Item *expr= min_max_item->get_arg(0)->real_item(); @@ -12630,26 +13119,41 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) if (! min_max_arg_item) min_max_arg_item= (Item_field*) expr; else if (! min_max_arg_item->eq(expr, 1)) + { + trace_group.add("chosen", false) + .add("cause", "arguments different in min max function"); DBUG_RETURN(NULL); + } } else + { + trace_group.add("chosen", false) + .add("cause", "no field item in min max function"); DBUG_RETURN(NULL); + } } } /* Check (SA7). */ if (is_agg_distinct && (have_max || have_min)) { + trace_group.add("chosen", false) + .add("cause", "have both agg distinct and min max"); DBUG_RETURN(NULL); } /* Check (SA5). */ if (join->select_distinct) { + trace_group.add("distinct_query", true); while ((item= select_items_it++)) { if (item->real_item()->type() != Item::FIELD_ITEM) + { + trace_group.add("chosen", false) + .add("cause", "distinct field is expression"); DBUG_RETURN(NULL); + } } } @@ -12658,7 +13162,11 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) for (tmp_group= join->group_list; tmp_group; tmp_group= tmp_group->next) { if ((*tmp_group->item)->real_item()->type() != Item::FIELD_ITEM) + { + trace_group.add("chosen", false) + .add("cause", "group field is expression"); DBUG_RETURN(NULL); + } elements_in_group++; } @@ -12680,10 +13188,16 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) ha_rows cur_quick_prefix_records= 0; // We go through allowed indexes + Json_writer_array trace_indexes(thd, "potential_group_range_indexes"); + for (uint cur_param_idx= 0; cur_param_idx < param->keys ; ++cur_param_idx) { const uint cur_index= param->real_keynr[cur_param_idx]; KEY *const cur_index_info= &table->key_info[cur_index]; + + Json_writer_object trace_idx(thd); + trace_idx.add("index", cur_index_info->name); + KEY_PART_INFO *cur_part; KEY_PART_INFO *end_part; /* Last part for loops. */ /* Last index part. */ @@ -12708,7 +13222,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) */ if (!table->covering_keys.is_set(cur_index) || !table->keys_in_use_for_group_by.is_set(cur_index)) - continue; + { + cause= "not covering"; + goto next_index; + } /* This function is called on the precondition that the index is covering. @@ -12716,7 +13233,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) these are duplicates. The GROUP BY list cannot be a prefix of the index. */ if (elements_in_group > table->actual_n_key_parts(cur_index_info)) - continue; + { + cause= "group key parts greater than index key parts"; + goto next_index; + } /* Unless extended keys can be used for cur_index: @@ -12742,10 +13262,15 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) */ if (bitmap_is_set(table->read_set, cur_field->field_index) && !cur_field->part_of_key_not_clustered.is_set(cur_index)) + { + cause= "not covering"; goto next_index; // Field was not part of key + } } } + trace_idx.add("covering", true); + max_key_part= 0; used_key_parts_map.clear_all(); @@ -12776,7 +13301,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) used_key_parts_map.set_bit(max_key_part); } else + { + cause= "group attribute not prefix in index"; goto next_index; + } } } /* @@ -12805,7 +13333,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) /* not doing loose index scan for derived tables */ if (!item_field->field) + { + cause= "derived table"; goto next_index; + } /* Find the order of the key part in the index. */ key_part_nr= get_field_keypart(cur_index_info, item_field->field); @@ -12817,7 +13348,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) continue; if (key_part_nr < 1 || (!is_agg_distinct && key_part_nr > join->fields_list.elements)) + { + cause= "select attribute not prefix in index"; goto next_index; + } cur_part= cur_index_info->key_part + key_part_nr - 1; cur_group_prefix_len+= cur_part->store_length; used_key_parts_map.set_bit(key_part_nr); @@ -12842,7 +13376,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) { key_part_nr= get_field_keypart(cur_index_info, min_max_arg_item->field); if (key_part_nr <= cur_group_key_parts) + { + cause = "aggregate column not suffix in idx"; goto next_index; + } min_max_arg_part= cur_index_info->key_part + key_part_nr - 1; } @@ -12853,6 +13390,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) if (cur_index_info->flags & HA_NOSAME && cur_group_key_parts == cur_index_info->user_defined_key_parts) { + cause= "using unique index"; goto next_index; } @@ -12892,7 +13430,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) last_part, thd, cur_key_infix, &cur_key_infix_len, &first_non_infix_part)) + { + cause = "nonconst equality gap attribute"; goto next_index; + } } else if (min_max_arg_part && (min_max_arg_part - first_non_group_part > 0)) @@ -12901,6 +13442,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) There is a gap but no range tree, thus no predicates at all for the non-group keyparts. */ + cause = "no nongroup keypart predicate"; goto next_index; } else if (first_non_group_part && join->conds) @@ -12924,7 +13466,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) /* Check if cur_part is referenced in the WHERE clause. */ if (join->conds->walk(&Item::find_item_in_field_list_processor, 0, key_part_range)) + { + cause = "keypart reference from where clause"; goto next_index; + } } } @@ -12939,7 +13484,10 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) for (; cur_part != last_part; cur_part++) { if (bitmap_is_set(table->read_set, cur_part->field->field_index)) + { + cause = "keypart after infix in query"; goto next_index; + } } } @@ -12956,6 +13504,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) index_range_tree, &cur_range) || (cur_range && cur_range->type != SEL_ARG::KEY_RANGE)) { + cause = "minmax keypart in disjunctive query"; goto next_index; } } @@ -12978,6 +13527,17 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) cur_index_tree, TRUE, &mrr_flags, &mrr_bufsize, &dummy_cost); + if (unlikely(cur_index_tree && thd->trace_started())) + { + Json_writer_array trace_range(thd, "ranges"); + + const KEY_PART_INFO *key_part = cur_index_info->key_part; + + String range_info; + range_info.set_charset(system_charset_info); + append_range_all_keyparts(&trace_range, NULL, &range_info, + cur_index_tree, key_part); + } } cost_group_min_max(table, cur_index_info, cur_used_key_parts, cur_group_key_parts, tree, cur_index_tree, @@ -12988,6 +13548,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) Do not compare doubles directly because they may have different representations (64 vs. 80 bits). */ + trace_idx.add("rows", cur_records).add("cost", cur_read_cost); + if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost)) { index_info= cur_index_info; @@ -13005,8 +13567,16 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) used_key_parts= cur_used_key_parts; } - next_index:; + next_index: + if (cause) + { + trace_idx.add("usable", false).add("cause", cause); + cause = NULL; + } } + + trace_indexes.end(); + if (!index_info) /* No usable index found. */ DBUG_RETURN(NULL); @@ -13017,14 +13587,22 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) (index_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW, &has_min_max_fld, &has_other_fld)) + { + trace_group.add("usable", false) + .add("cause", "unsupported predicate on agg attribute"); DBUG_RETURN(NULL); + } /* Check (SA6) if clustered key is used */ if (is_agg_distinct && index == table->s->primary_key && table->file->primary_key_is_clustered()) + { + trace_group.add("usable", false) + .add("cause", "index is clustered"); DBUG_RETURN(NULL); + } /* The query passes all tests, so construct a new TRP object. */ read_plan= new (param->mem_root) @@ -13045,6 +13623,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) read_plan->records= best_records; if (read_time < best_read_cost && is_agg_distinct) { + trace_group.add("index_scan", true); read_plan->read_cost= 0; read_plan->use_index_scan(); } @@ -15002,7 +15581,6 @@ static void print_quick(QUICK_SELECT_I *quick, const key_map *needed_reg) DBUG_VOID_RETURN; } - void QUICK_RANGE_SELECT::dbug_dump(int indent, bool verbose) { /* purecov: begin inspected */ @@ -15130,3 +15708,174 @@ void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose) } #endif /* !DBUG_OFF */ +static +void append_range(String *out, const KEY_PART_INFO *key_part, + const uchar *min_key, const uchar *max_key, const uint flag) +{ + if (out->length() > 0) + out->append(STRING_WITH_LEN(" AND ")); + + if (flag & GEOM_FLAG) + { + /* + The flags of GEOM ranges do not work the same way as for other + range types, so printing "col < some_geom" doesn't make sense. + Just print the column name, not operator. + */ + out->append(key_part->field->field_name); + out->append(STRING_WITH_LEN(" ")); + print_key_value(out, key_part, min_key); + return; + } + + if (!(flag & NO_MIN_RANGE)) + { + print_key_value(out, key_part, min_key); + if (flag & NEAR_MIN) + out->append(STRING_WITH_LEN(" < ")); + else + out->append(STRING_WITH_LEN(" <= ")); + } + + out->append(key_part->field->field_name); + + if (!(flag & NO_MAX_RANGE)) + { + if (flag & NEAR_MAX) + out->append(STRING_WITH_LEN(" < ")); + else + out->append(STRING_WITH_LEN(" <= ")); + print_key_value(out, key_part, max_key); + } +} + +/* + + Add ranges to the trace + For ex: + query: select * from t1 where a=2 ; + and we have an index on a , so we create a range + 2 <= a <= 2 + this is added to the trace +*/ + +static void append_range_all_keyparts(Json_writer_array *range_trace, + String *range_string, + String *range_so_far, const SEL_ARG *keypart, + const KEY_PART_INFO *key_parts) +{ + + DBUG_ASSERT(keypart); + DBUG_ASSERT(keypart && keypart != &null_element); + + // Navigate to first interval in red-black tree + const KEY_PART_INFO *cur_key_part = key_parts + keypart->part; + const SEL_ARG *keypart_range = keypart->first(); + const size_t save_range_so_far_length = range_so_far->length(); + + + while (keypart_range) + { + // Append the current range predicate to the range String + switch (keypart->type) + { + case SEL_ARG::Type::KEY_RANGE: + append_range(range_so_far, cur_key_part, keypart_range->min_value, + keypart_range->max_value, + keypart_range->min_flag | keypart_range->max_flag); + break; + case SEL_ARG::Type::MAYBE_KEY: + range_so_far->append("MAYBE_KEY"); + break; + case SEL_ARG::Type::IMPOSSIBLE: + range_so_far->append("IMPOSSIBLE"); + break; + default: + DBUG_ASSERT(false); + break; + } + + if (keypart_range->next_key_part && + keypart_range->next_key_part->part == + keypart_range->part + 1 && + keypart_range->is_singlepoint()) + { + append_range_all_keyparts(range_trace, range_string, range_so_far, + keypart_range->next_key_part, key_parts); + } + else + range_trace->add(range_so_far->c_ptr_safe(), range_so_far->length()); + keypart_range= keypart_range->next; + range_so_far->length(save_range_so_far_length); + } +} + +/** + Print a key to a string + + @param[out] out String the key is appended to + @param[in] key_part Index components description + @param[in] key Key tuple +*/ +static void print_key_value(String *out, const KEY_PART_INFO *key_part, + const uchar *key) +{ + Field *field = key_part->field; + + if (field->flags & BLOB_FLAG) { + // Byte 0 of a nullable key is the null-byte. If set, key is NULL. + if (field->real_maybe_null() && *key) + out->append(STRING_WITH_LEN("NULL")); + else + (field->type() == MYSQL_TYPE_GEOMETRY) + ? out->append(STRING_WITH_LEN("unprintable_geometry_value")) + : out->append(STRING_WITH_LEN("unprintable_blob_value")); + return; + } + + uint store_length = key_part->store_length; + + if (field->real_maybe_null()) + { + /* + Byte 0 of key is the null-byte. If set, key is NULL. + Otherwise, print the key value starting immediately after the + null-byte + */ + if (*key) { + out->append(STRING_WITH_LEN("NULL")); + return; + } + key++; // Skip null byte + store_length--; + } + + /* + Binary data cannot be converted to UTF8 which is what the + optimizer trace expects. If the column is binary, the hex + representation is printed to the trace instead. + */ + if (field->flags & BINARY_FLAG) { + out->append("0x"); + for (uint i = 0; i < store_length; i++) { + out->append(_dig_vec_lower[*(key + i) >> 4]); + out->append(_dig_vec_lower[*(key + i) & 0x0F]); + } + return; + } + + StringBuffer<128> tmp(system_charset_info); + TABLE *table = field->table; + my_bitmap_map *old_sets[2]; + + dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set); + + field->set_key_image(key, key_part->length); + if (field->type() == MYSQL_TYPE_BIT) + (void)field->val_int_as_str(&tmp, 1); // may change tmp's charset + else + field->val_str(&tmp); // may change tmp's charset + out->append(tmp.ptr(), tmp.length(), tmp.charset()); + + dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets); +} diff --git a/sql/opt_range.h b/sql/opt_range.h index d5416988b88..7e92e1f54ee 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -566,7 +566,7 @@ public: FALSE Otherwise */ - bool is_singlepoint() + bool is_singlepoint() const { /* Check for NEAR_MIN ("strictly less") and NO_MIN_RANGE (-inf < field) diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index c4c30c9b50d..228fcd0f7e6 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -33,6 +33,7 @@ #include "opt_subselect.h" #include "sql_test.h" #include +#include "opt_trace.h" /* This file contains optimizations for semi-join subqueries. @@ -437,7 +438,7 @@ Currently, solution #2 is implemented. LEX_CSTRING weedout_key= {STRING_WITH_LEN("weedout_key")}; static -bool subquery_types_allow_materialization(Item_in_subselect *in_subs); +bool subquery_types_allow_materialization(THD *thd, Item_in_subselect *in_subs); static bool replace_where_subcondition(JOIN *, Item **, Item *, Item *, bool); static int subq_sj_candidate_cmp(Item_in_subselect* el1, Item_in_subselect* el2, void *arg); @@ -521,7 +522,7 @@ bool is_materialization_applicable(THD *thd, Item_in_subselect *in_subs, parent_unit->first_select()->leaf_tables.elements && // 2 child_select->outer_select() && child_select->outer_select()->leaf_tables.elements && // 2A - subquery_types_allow_materialization(in_subs) && + subquery_types_allow_materialization(thd, in_subs) && (in_subs->is_top_level_item() || //3 optimizer_flag(thd, OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE) || //3 @@ -682,7 +683,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join) { DBUG_PRINT("info", ("Subquery is semi-join conversion candidate")); - (void)subquery_types_allow_materialization(in_subs); + (void)subquery_types_allow_materialization(thd, in_subs); in_subs->is_flattenable_semijoin= TRUE; @@ -696,6 +697,9 @@ int check_and_do_in_subquery_rewrites(JOIN *join) if (arena) thd->restore_active_arena(arena, &backup); in_subs->is_registered_semijoin= TRUE; + OPT_TRACE_TRANSFORM(thd, oto0, oto1, select_lex->select_number, + "IN (SELECT)", "semijoin"); + oto1.add("chosen", true); } } else @@ -823,7 +827,7 @@ int check_and_do_in_subquery_rewrites(JOIN *join) */ static -bool subquery_types_allow_materialization(Item_in_subselect *in_subs) +bool subquery_types_allow_materialization(THD* thd, Item_in_subselect *in_subs) { DBUG_ENTER("subquery_types_allow_materialization"); @@ -831,9 +835,14 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs) List_iterator it(in_subs->unit->first_select()->item_list); uint elements= in_subs->unit->first_select()->item_list.elements; + const char* cause= NULL; in_subs->types_allow_materialization= FALSE; // Assign default values in_subs->sjm_scan_allowed= FALSE; + + OPT_TRACE_TRANSFORM(thd, oto0, oto1, + in_subs->get_select_lex()->select_number, + "IN (SELECT)", "materialization"); bool all_are_fields= TRUE; uint32 total_key_length = 0; @@ -846,7 +855,11 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs) total_key_length += inner->max_length; if (!inner->type_handler()->subquery_type_allows_materialization(inner, outer)) + { + oto1.add("possible", false); + oto1.add("cause", "types mismatch"); DBUG_RETURN(FALSE); + } } /* @@ -856,14 +869,23 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs) Make sure that the length of the key for the temp_table is atleast greater than 0. */ - if (!total_key_length || total_key_length > tmp_table_max_key_length() || - elements > tmp_table_max_key_parts()) - DBUG_RETURN(FALSE); - - in_subs->types_allow_materialization= TRUE; - in_subs->sjm_scan_allowed= all_are_fields; - DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed")); - DBUG_RETURN(TRUE); + if (!total_key_length) + cause= "zero length key for materialized table"; + else if (total_key_length > tmp_table_max_key_length()) + cause= "length of key greater than allowed key length for materialized tables"; + else if (elements > tmp_table_max_key_parts()) + cause= "#keyparts greater than allowed key parts for materialized tables"; + else + { + in_subs->types_allow_materialization= TRUE; + in_subs->sjm_scan_allowed= all_are_fields; + oto1.add("sjm_scan_allowed", all_are_fields) + .add("possible", true); + DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed")); + DBUG_RETURN(TRUE); + } + oto1.add("possible", false).add("cause", cause); + DBUG_RETURN(FALSE); } @@ -1213,15 +1235,30 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) /* Stop processing if we've reached a subquery that's attached to the ON clause */ if (in_subq->do_not_convert_to_sj) + { + OPT_TRACE_TRANSFORM(thd, oto0, oto1, + in_subq->get_select_lex()->select_number, + "IN (SELECT)", "semijoin"); + oto1.add("converted_to_semi_join", false) + .add("cause", "subquery attached to the ON clause"); break; + } if (in_subq->is_flattenable_semijoin) { + OPT_TRACE_TRANSFORM(thd, oto0, oto1, + in_subq->get_select_lex()->select_number, + "IN (SELECT)", "semijoin"); if (join->table_count + in_subq->unit->first_select()->join->table_count >= MAX_TABLES) + { + oto1.add("converted_to_semi_join", false); + oto1.add("cause", "table in parent join now exceeds MAX_TABLES"); break; + } if (convert_subq_to_sj(join, in_subq)) goto restore_arena_and_fail; + oto1.add("converted_to_semi_join", true); } else { @@ -2340,8 +2377,13 @@ int pull_out_semijoin_tables(JOIN *join) bool optimize_semijoin_nests(JOIN *join, table_map all_table_map) { DBUG_ENTER("optimize_semijoin_nests"); + THD *thd= join->thd; List_iterator sj_list_it(join->select_lex->sj_nests); TABLE_LIST *sj_nest; + Json_writer_object wrapper(thd); + Json_writer_object trace_semijoin_nest(thd, + "execution_plan_for_potential_materialization"); + Json_writer_array trace_steps_array(thd, "steps"); while ((sj_nest= sj_list_it++)) { /* semi-join nests with only constant tables are not valid */ diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc index 74d1e775c43..03516146de2 100644 --- a/sql/opt_table_elimination.cc +++ b/sql/opt_table_elimination.cc @@ -31,6 +31,8 @@ #include "mariadb.h" #include "my_bit.h" #include "sql_select.h" +#include "opt_trace.h" +#include "my_json_writer.h" /* OVERVIEW @@ -522,7 +524,8 @@ eliminate_tables_for_list(JOIN *join, List *join_list, table_map tables_in_list, Item *on_expr, - table_map tables_used_elsewhere); + table_map tables_used_elsewhere, + Json_writer_array* eliminate_tables); static bool check_func_dependency(JOIN *join, table_map dep_tables, @@ -541,7 +544,8 @@ static Dep_module_expr *merge_eq_mods(Dep_module_expr *start, Dep_module_expr *new_fields, Dep_module_expr *end, uint and_level); -static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl); +static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl, + Json_writer_array* eliminate_tables); static void add_module_expr(Dep_analysis_context *dac, Dep_module_expr **eq_mod, uint and_level, Dep_value_field *field_val, Item *right, @@ -608,6 +612,8 @@ void eliminate_tables(JOIN *join) if (!optimizer_flag(thd, OPTIMIZER_SWITCH_TABLE_ELIMINATION)) DBUG_VOID_RETURN; /* purecov: inspected */ + Json_writer_object trace_wrapper(thd); + /* Find the tables that are referred to from WHERE/HAVING */ used_tables= (join->conds? join->conds->used_tables() : 0) | (join->having? join->having->used_tables() : 0); @@ -663,13 +669,14 @@ void eliminate_tables(JOIN *join) } } } - + table_map all_tables= join->all_tables_map(); + Json_writer_array eliminated_tables(thd,"eliminated_tables"); if (all_tables & ~used_tables) { /* There are some tables that we probably could eliminate. Try it. */ eliminate_tables_for_list(join, join->join_list, all_tables, NULL, - used_tables); + used_tables, &eliminated_tables); } DBUG_VOID_RETURN; } @@ -712,7 +719,8 @@ void eliminate_tables(JOIN *join) static bool eliminate_tables_for_list(JOIN *join, List *join_list, table_map list_tables, Item *on_expr, - table_map tables_used_elsewhere) + table_map tables_used_elsewhere, + Json_writer_array *eliminate_tables) { TABLE_LIST *tbl; List_iterator it(*join_list); @@ -734,9 +742,9 @@ eliminate_tables_for_list(JOIN *join, List *join_list, &tbl->nested_join->join_list, tbl->nested_join->used_tables, tbl->on_expr, - outside_used_tables)) + outside_used_tables, eliminate_tables)) { - mark_as_eliminated(join, tbl); + mark_as_eliminated(join, tbl, eliminate_tables); } else all_eliminated= FALSE; @@ -748,7 +756,7 @@ eliminate_tables_for_list(JOIN *join, List *join_list, check_func_dependency(join, tbl->table->map, NULL, tbl, tbl->on_expr)) { - mark_as_eliminated(join, tbl); + mark_as_eliminated(join, tbl, eliminate_tables); } else all_eliminated= FALSE; @@ -1788,7 +1796,8 @@ Dep_module* Dep_value_field::get_next_unbound_module(Dep_analysis_context *dac, Mark one table or the whole join nest as eliminated. */ -static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl) +static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl, + Json_writer_array* eliminate_tables) { TABLE *table; /* @@ -1801,7 +1810,7 @@ static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl) TABLE_LIST *child; List_iterator it(tbl->nested_join->join_list); while ((child= it++)) - mark_as_eliminated(join, child); + mark_as_eliminated(join, child, eliminate_tables); } else if ((table= tbl->table)) { @@ -1812,6 +1821,7 @@ static void mark_as_eliminated(JOIN *join, TABLE_LIST *tbl) tab->type= JT_CONST; tab->table->const_table= 1; join->eliminated_tables |= table->map; + eliminate_tables->add(table->alias.c_ptr_safe()); join->const_table_map|= table->map; set_position(join, join->const_tables++, tab, (KEYUSE*)0); } diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc new file mode 100644 index 00000000000..ca05f36579a --- /dev/null +++ b/sql/opt_trace.cc @@ -0,0 +1,722 @@ +/* This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "mariadb.h" +#include "sql_array.h" +#include "sql_string.h" +#include "sql_class.h" +#include "sql_show.h" +#include "field.h" +#include "table.h" +#include "opt_trace.h" +#include "sql_parse.h" +#include "set_var.h" +#include "my_json_writer.h" +#include "sp_head.h" + +const char I_S_table_name[] = "OPTIMIZER_TRACE"; + +/** + Whether a list of tables contains information_schema.OPTIMIZER_TRACE. + @param tbl list of tables + + Can we do better than this here?? + @note this does not catch that a stored routine or view accesses + the OPTIMIZER_TRACE table. So using a stored routine or view to read + OPTIMIZER_TRACE will overwrite OPTIMIZER_TRACE as it runs and provide + uninteresting info. +*/ +bool list_has_optimizer_trace_table(const TABLE_LIST *tbl) +{ + for (; tbl; tbl = tbl->next_global) + { + if (tbl->schema_table && + 0 == strcmp(tbl->schema_table->table_name, I_S_table_name)) + return true; + } + return false; +} + +/* + Returns if a query has a set command with optimizer_trace being switched on/off. + True: Don't trace the query(uninteresting) +*/ + +bool sets_var_optimizer_trace(enum enum_sql_command sql_command, + List *set_vars) +{ + if (sql_command == SQLCOM_SET_OPTION) + { + List_iterator_fast it(*set_vars); + const set_var_base *var; + while ((var = it++)) + if (var->is_var_optimizer_trace()) return true; + } + return false; +} + + +ST_FIELD_INFO optimizer_trace_info[] = { + /* name, length, type, value, maybe_null, old_name, open_method */ + {"QUERY", 65535, MYSQL_TYPE_STRING, 0, false, NULL, SKIP_OPEN_TABLE}, + {"TRACE", 65535, MYSQL_TYPE_STRING, 0, false, NULL, SKIP_OPEN_TABLE}, + {"MISSING_BYTES_BEYOND_MAX_MEM_SIZE", 20, MYSQL_TYPE_LONG, 0, false, NULL, + SKIP_OPEN_TABLE}, + {"INSUFFICIENT_PRIVILEGES", 1, MYSQL_TYPE_TINY, 0, false, NULL, + SKIP_OPEN_TABLE}, + {NULL, 0, MYSQL_TYPE_STRING, 0, true, NULL, 0}}; + +/* + TODO: one-line needs to be implemented seperately +*/ +const char *Opt_trace_context::flag_names[] = {"enabled", "default", + NullS}; + +/* + Returns if a particular command will be traced or not +*/ + +inline bool sql_command_can_be_traced(enum enum_sql_command sql_command) +{ + /* + For first iteration we are only allowing select queries. + TODO: change to allow other queries. + */ + return sql_command == SQLCOM_SELECT || + sql_command == SQLCOM_UPDATE || + sql_command == SQLCOM_DELETE || + sql_command == SQLCOM_DELETE_MULTI || + sql_command == SQLCOM_UPDATE_MULTI; +} + +void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex, + Json_writer_object *writer) + +{ + if (!thd->trace_started()) + return; + char buff[1024]; + String str(buff, sizeof(buff), system_charset_info); + str.length(0); + select_lex->print(thd, &str, + enum_query_type(QT_TO_SYSTEM_CHARSET | + QT_SHOW_SELECT_NUMBER | + QT_ITEM_IDENT_SKIP_DB_NAMES | + QT_VIEW_INTERNAL + )); + /* + The output is not very pretty lots of back-ticks, the output + is as the one in explain extended , lets try to improved it here. + */ + writer->add("expanded_query", str.c_ptr_safe(), str.length()); +} + +void opt_trace_disable_if_no_security_context_access(THD *thd) +{ + if (likely(!(thd->variables.optimizer_trace & + Opt_trace_context::FLAG_ENABLED)) || // (1) + thd->system_thread) // (2) + { + /* + (1) We know that the routine's execution starts with "enabled=off". + If it stays so until the routine ends, we needn't do security checks on + the routine. + If it does not stay so, it means the definer sets it to "on" somewhere + in the routine's body. Then it is his conscious decision to generate + traces, thus it is still correct to skip the security check. + + (2) Threads of the Events Scheduler have an unusual security context + (thd->m_main_security_ctx.priv_user==NULL, see comment in + Security_context::change_security_context()). + */ + return; + } + Opt_trace_context *const trace = &thd->opt_trace; + if (!thd->trace_started()) + { + /* + @@optimizer_trace has "enabled=on" but trace is not started. + Either Opt_trace_start ctor was not called for our statement (3), or it + was called but at that time, the variable had "enabled=off" (4). + + There are no known cases of (3). + + (4) suggests that the user managed to change the variable during + execution of the statement, and this statement is using + view/routine (note that we have not been able to provoke this, maybe + this is impossible). If it happens it is suspicious. + + We disable I_S output. And we cannot do otherwise: we have no place to + store a possible "missing privilege" information (no Opt_trace_stmt, as + is_started() is false), so cannot do security checks, so cannot safely + do tracing, so have to disable I_S output. And even then, we don't know + when to re-enable I_S output, as we have no place to store the + information "re-enable tracing at the end of this statement", and we + don't even have a notion of statement here (statements in the optimizer + trace world mean an Opt_trace_stmt object, and there is none here). So + we must disable for the session's life. + + COM_FIELD_LIST opens views, thus used to be a case of (3). To avoid + disabling I_S output for the session's life when this command is issued + (like in: "SET OPTIMIZER_TRACE='ENABLED=ON';USE somedb;" in the 'mysql' + command-line client), we have decided to create a Opt_trace_start for + this command. The command itself is not traced though + (SQLCOM_SHOW_FIELDS does not have CF_OPTIMIZER_TRACE). + */ + return; + } + /* + Note that thd->main_security_ctx.master_access is probably invariant + accross the life of THD: GRANT/REVOKE don't affect global privileges of an + existing connection, per the manual. + */ + if (!(thd->main_security_ctx.check_access(GLOBAL_ACLS & ~GRANT_ACL)) && + (0 != strcmp(thd->main_security_ctx.priv_user, + thd->security_context()->priv_user) || + 0 != my_strcasecmp(system_charset_info, + thd->main_security_ctx.priv_host, + thd->security_context()->priv_host))) + trace->missing_privilege(); + return; +} + +void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp) +{ + if (likely(!(thd->variables.optimizer_trace & + Opt_trace_context::FLAG_ENABLED)) || + thd->system_thread) + return; + + Opt_trace_context *const trace = &thd->opt_trace; + if (!thd->trace_started()) + return; + bool full_access; + Security_context *const backup_thd_sctx = thd->security_context(); + thd->set_security_context(&thd->main_security_ctx); + const bool rc = check_show_routine_access(thd, sp, &full_access) || !full_access; + thd->set_security_context(backup_thd_sctx); + if (rc) + trace->missing_privilege(); + return; +} + +/** + If tracing is on, checks additional privileges on a list of tables/views, + to make sure that the user has the right to do SHOW CREATE TABLE/VIEW and + "SELECT *". For that: + - this functions checks table-level SELECT + - which is sufficient for SHOW CREATE TABLE and "SELECT *", if a base table + - if a view, if the view has not been identified as such then + opt_trace_disable_if_no_view_access() will be later called and check SHOW + VIEW; other we check SHOW VIEW here; SHOW VIEW + SELECT is sufficient for + SHOW CREATE VIEW. + If a privilege is missing, notifies the trace system. + + @param thd + @param tbl list of tables to check +*/ + +void opt_trace_disable_if_no_tables_access(THD *thd, TABLE_LIST *tbl) +{ + if (likely(!(thd->variables.optimizer_trace & + Opt_trace_context::FLAG_ENABLED)) || thd->system_thread) + return; + Opt_trace_context *const trace = &thd->opt_trace; + + if (!thd->trace_started()) + return; + + Security_context *const backup_thd_sctx = thd->security_context(); + thd->set_security_context(&thd->main_security_ctx); + const TABLE_LIST *const first_not_own_table = thd->lex->first_not_own_table(); + for (TABLE_LIST *t = tbl; t != NULL && t != first_not_own_table; + t = t->next_global) + { + /* + Anonymous derived tables (as in + "SELECT ... FROM (SELECT ...)") don't have their grant.privilege set. + */ + if (!t->is_anonymous_derived_table()) + { + const GRANT_INFO backup_grant_info = t->grant; + Security_context *const backup_table_sctx = t->security_ctx; + t->security_ctx = NULL; + /* + (1) check_table_access() fills t->grant.privilege. + (2) Because SELECT privileges can be column-based, + check_table_access() will return 'false' as long as there is SELECT + privilege on one column. But we want a table-level privilege. + */ + + bool rc = + check_table_access(thd, SELECT_ACL, t, false, 1, true) || // (1) + ((t->grant.privilege & SELECT_ACL) == 0); // (2) + if (t->is_view()) + { + /* + It's a view which has already been opened: we are executing a + prepared statement. The view has been unfolded in the global list of + tables. So underlying tables will be automatically checked in the + present function, but we need an explicit check of SHOW VIEW: + */ + rc |= check_table_access(thd, SHOW_VIEW_ACL, t, false, 1, true); + } + t->security_ctx = backup_table_sctx; + t->grant = backup_grant_info; + if (rc) + { + trace->missing_privilege(); + break; + } + } + } + thd->set_security_context(backup_thd_sctx); + return; +} + +void opt_trace_disable_if_no_view_access(THD *thd, TABLE_LIST *view, + TABLE_LIST *underlying_tables) +{ + + if (likely(!(thd->variables.optimizer_trace & + Opt_trace_context::FLAG_ENABLED)) || + thd->system_thread) + return; + Opt_trace_context *const trace = &thd->opt_trace; + if (!thd->trace_started()) + return; + + Security_context *const backup_table_sctx = view->security_ctx; + Security_context *const backup_thd_sctx = thd->security_context(); + const GRANT_INFO backup_grant_info = view->grant; + + view->security_ctx = NULL; // no SUID context for view + // no SUID context for THD + thd->set_security_context(&thd->main_security_ctx); + const int rc = check_table_access(thd, SHOW_VIEW_ACL, view, false, 1, true); + + view->security_ctx = backup_table_sctx; + thd->set_security_context(backup_thd_sctx); + view->grant = backup_grant_info; + + if (rc) + { + trace->missing_privilege(); + return; + } + /* + We needn't check SELECT privilege on this view. Some + opt_trace_disable_if_no_tables_access() call has or will check it. + + Now we check underlying tables/views of our view: + */ + opt_trace_disable_if_no_tables_access(thd, underlying_tables); + return; +} + + +/** + @class Opt_trace_stmt + + The trace of one statement. +*/ + +class Opt_trace_stmt { + public: + /** + Constructor, starts a trace for information_schema and dbug. + @param ctx_arg context + */ + Opt_trace_stmt(Opt_trace_context *ctx_arg) + { + ctx= ctx_arg; + current_json= new Json_writer(); + missing_priv= false; + I_S_disabled= 0; + } + ~Opt_trace_stmt() + { + delete current_json; + missing_priv= false; + ctx= NULL; + I_S_disabled= 0; + } + void set_query(const char *query_ptr, size_t length, const CHARSET_INFO *charset); + void open_struct(const char *key, char opening_bracket); + void close_struct(const char *saved_key, char closing_bracket); + void fill_info(Opt_trace_info* info); + void add(const char *key, char *opening_bracket, size_t val_length); + Json_writer* get_current_json(){return current_json;} + void missing_privilege(); + void disable_tracing_for_children(); + void enable_tracing_for_children(); + bool is_enabled(); + + void set_allowed_mem_size(size_t mem_size); + size_t get_length() { return current_json->output.length(); } + size_t get_truncated_bytes() { return current_json->get_truncated_bytes(); } + bool get_missing_priv() { return missing_priv; } + +private: + Opt_trace_context *ctx; + String query; // store the query sent by the user + Json_writer *current_json; // stores the trace + bool missing_priv; ///< whether user lacks privilege to see this trace + uint I_S_disabled; +}; + +void Opt_trace_stmt::set_query(const char *query_ptr, size_t length, + const CHARSET_INFO *charset) +{ + query.append(query_ptr, length, charset); +} + +Json_writer* Opt_trace_context::get_current_json() +{ + if (!is_started()) + return NULL; + return current_trace->get_current_json(); +} + +void Opt_trace_context::missing_privilege() +{ + if (current_trace) + current_trace->missing_privilege(); +} + +void Opt_trace_context::set_allowed_mem_size(size_t mem_size) +{ + current_trace->set_allowed_mem_size(mem_size); +} + +/* + TODO: In future when we would be saving multiple trace, + this function would return + max_mem_size - memory_occupied_by_the_saved_traces +*/ + +size_t Opt_trace_context::remaining_mem_size() +{ + return max_mem_size; +} + +bool Opt_trace_context::disable_tracing_if_required() +{ + if (current_trace) + { + current_trace->disable_tracing_for_children(); + return true; + } + return false; +} + +bool Opt_trace_context::enable_tracing_if_required() +{ + if (current_trace) + { + current_trace->enable_tracing_for_children(); + return true; + } + return false; +} + +bool Opt_trace_context::is_enabled() +{ + if (current_trace) + return current_trace->is_enabled(); + return false; +} + +Opt_trace_context::Opt_trace_context() +{ + current_trace= NULL; + inited= FALSE; + traces= NULL; + max_mem_size= 0; +} +Opt_trace_context::~Opt_trace_context() +{ + inited= FALSE; + /* + would be nice to move this to a function + */ + if (traces) + { + while (traces->elements()) + { + Opt_trace_stmt *prev= traces->at(0); + delete prev; + traces->del(0); + } + delete traces; + traces= NULL; + } + max_mem_size= 0; +} + +void Opt_trace_context::set_query(const char *query, size_t length, const CHARSET_INFO *charset) +{ + current_trace->set_query(query, length, charset); +} + +void Opt_trace_context::start(THD *thd, TABLE_LIST *tbl, + enum enum_sql_command sql_command, + const char *query, + size_t query_length, + const CHARSET_INFO *query_charset, + ulong max_mem_size_arg) +{ + /* + This is done currently because we don't want to have multiple + traces open at the same time, so as soon as a new trace is created + we forcefully end the previous one, if it has not ended by itself. + This would mostly happen with stored functions or procedures. + + TODO: handle multiple traces + */ + DBUG_ASSERT(!current_trace); + current_trace= new Opt_trace_stmt(this); + max_mem_size= max_mem_size_arg; + if (!inited) + { + traces= new Dynamic_array(); + inited= TRUE; + } + set_allowed_mem_size(remaining_mem_size()); +} + +void Opt_trace_context::end() +{ + if (current_trace) + traces->push(current_trace); + + if (!traces->elements()) + return; + if (traces->elements() > 1) + { + Opt_trace_stmt *prev= traces->at(0); + delete prev; + traces->del(0); + } + current_trace= NULL; +} + +Opt_trace_start::Opt_trace_start(THD *thd, TABLE_LIST *tbl, + enum enum_sql_command sql_command, + List *set_vars, + const char *query, + size_t query_length, + const CHARSET_INFO *query_charset):ctx(&thd->opt_trace) +{ + /* + if optimizer trace is enabled and the statment we have is traceable, + then we start the context. + */ + const ulonglong var = thd->variables.optimizer_trace; + traceable= FALSE; + if (unlikely(var & Opt_trace_context::FLAG_ENABLED) && + sql_command_can_be_traced(sql_command) && + !list_has_optimizer_trace_table(tbl) && + !sets_var_optimizer_trace(sql_command, set_vars) && + !thd->system_thread && + !ctx->disable_tracing_if_required()) + { + ctx->start(thd, tbl, sql_command, query, query_length, query_charset, + thd->variables.optimizer_trace_max_mem_size); + ctx->set_query(query, query_length, query_charset); + traceable= TRUE; + opt_trace_disable_if_no_tables_access(thd, tbl); + } +} + +Opt_trace_start::~Opt_trace_start() +{ + if (traceable) + { + ctx->end(); + traceable= FALSE; + } + else + { + ctx->enable_tracing_if_required(); + } +} + +void Opt_trace_stmt::fill_info(Opt_trace_info* info) +{ + if (unlikely(info->missing_priv = get_missing_priv())) + { + info->trace_ptr = info->query_ptr = ""; + info->trace_length = info->query_length = 0; + info->query_charset = &my_charset_bin; + info->missing_bytes = 0; + } + else + { + info->trace_ptr = current_json->output.get_string()->ptr(); + info->trace_length = get_length(); + info->query_ptr = query.ptr(); + info->query_length = query.length(); + info->query_charset = query.charset(); + info->missing_bytes = get_truncated_bytes(); + info->missing_priv= get_missing_priv(); + } +} + +void Opt_trace_stmt::missing_privilege() +{ + missing_priv= true; +} + +void Opt_trace_stmt::disable_tracing_for_children() +{ + ++I_S_disabled; +} + +void Opt_trace_stmt::enable_tracing_for_children() +{ + if (I_S_disabled) + --I_S_disabled; +} + +bool Opt_trace_stmt::is_enabled() +{ + return I_S_disabled == 0; +} + +void Opt_trace_stmt::set_allowed_mem_size(size_t mem_size) +{ + current_json->set_size_limit(mem_size); +} + +/* + Prefer this when you are iterating over JOIN_TABs +*/ + +void Json_writer::add_table_name(const JOIN_TAB *tab) +{ + if (tab != NULL) + { + char table_name_buffer[SAFE_NAME_LEN]; + if (tab->table && tab->table->derived_select_number) + { + /* Derived table name generation */ + size_t len= my_snprintf(table_name_buffer, sizeof(table_name_buffer)-1, + "", + tab->table->derived_select_number); + add_str(table_name_buffer, len); + } + else if (tab->bush_children) + { + JOIN_TAB *ctab= tab->bush_children->start; + size_t len= my_snprintf(table_name_buffer, + sizeof(table_name_buffer)-1, + "", + ctab->emb_sj_nest->sj_subq_pred->get_identifier()); + add_str(table_name_buffer, len); + } + else + { + TABLE_LIST *real_table= tab->table->pos_in_table_list; + add_str(real_table->alias.str, real_table->alias.length); + } + } + else + DBUG_ASSERT(0); +} + +void Json_writer::add_table_name(const TABLE *table) +{ + add_str(table->pos_in_table_list->alias.str); +} + + +void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab) +{ + Json_writer_object table_records(thd); + table_records.add_table_name(tab); + Json_writer_object table_rec(thd, "table_scan"); + table_rec.add("rows", tab->found_records) + .add("cost", tab->read_time); +} +/* + Introduce enum_query_type flags parameter, maybe also allow + EXPLAIN also use this function. +*/ + +void Json_writer::add_str(Item *item) +{ + if (item) + { + THD *thd= current_thd; + char buff[256]; + String str(buff, sizeof(buff), system_charset_info); + str.length(0); + + ulonglong save_option_bits= thd->variables.option_bits; + thd->variables.option_bits &= ~OPTION_QUOTE_SHOW_CREATE; + item->print(&str, + enum_query_type(QT_TO_SYSTEM_CHARSET | QT_SHOW_SELECT_NUMBER + | QT_ITEM_IDENT_SKIP_DB_NAMES)); + thd->variables.option_bits= save_option_bits; + add_str(str.c_ptr_safe()); + } + else + add_null(); +} + +void Opt_trace_context::flush_optimizer_trace() +{ + inited= false; + if (traces) + { + while (traces->elements()) + { + Opt_trace_stmt *prev= traces->at(0); + delete prev; + traces->del(0); + } + delete traces; + traces= NULL; + } +} + + +int fill_optimizer_trace_info(THD *thd, TABLE_LIST *tables, Item *) +{ + TABLE *table = tables->table; + Opt_trace_info info; + + /* get_values of trace, query , missing bytes and missing_priv + + @todo: Need an iterator here to walk over all the traces + */ + Opt_trace_context* ctx= &thd->opt_trace; + + if (thd->opt_trace.empty()) + { + Opt_trace_stmt *stmt= ctx->get_top_trace(); + stmt->fill_info(&info); + + table->field[0]->store(info.query_ptr, static_cast(info.query_length), + info.query_charset); + table->field[1]->store(info.trace_ptr, static_cast(info.trace_length), + system_charset_info); + table->field[2]->store(info.missing_bytes, true); + table->field[3]->store(info.missing_priv, true); + // Store in IS + if (schema_table_store_record(thd, table)) + return 1; + } + return 0; +} diff --git a/sql/opt_trace.h b/sql/opt_trace.h new file mode 100644 index 00000000000..0e2d0146a49 --- /dev/null +++ b/sql/opt_trace.h @@ -0,0 +1,201 @@ +#ifndef OPT_TRACE_INCLUDED +#define OPT_TRACE_INCLUDED +/* This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "opt_trace_context.h" // Opt_trace_context +#include "sql_lex.h" +#include "my_json_writer.h" +#include "sql_select.h" +class Item; +class THD; +struct TABLE_LIST; + +class Opt_trace_stmt; + +/* + User-visible information about a trace. +*/ + +struct Opt_trace_info +{ + /** + String containing trace. + If trace has been end()ed, this is 0-terminated, which is only to aid + debugging or unit testing; this property is not relied upon in normal + server usage. + If trace has not been ended, this is not 0-terminated. That rare case can + happen when a substatement reads OPTIMIZER_TRACE (at that stage, the top + statement is still executing so its trace is not ended yet, but may still + be read by the sub-statement). + */ + const char *trace_ptr; + size_t trace_length; + //// String containing original query. + const char *query_ptr; + size_t query_length; + const CHARSET_INFO *query_charset; ///< charset of query string + /** + How many bytes this trace is missing (for traces which were truncated + because of @@@@optimizer-trace-max-mem-size). + The trace is not extended beyond trace-max-mem-size. + */ + size_t missing_bytes; + /* + Whether user lacks privilege to see this trace. + If this is set to TRUE, then we return an empty trace + */ + bool missing_priv; +}; + +/** + Instantiate this class to start tracing a THD's actions (generally at a + statement's start), and to set the "original" query (not transformed, as + sent by client) for the new trace. Destructor will end the trace. + + @param thd the THD + @param tbl list of tables read/written by the statement. + @param sql_command SQL command being prepared or executed + @param set_vars what variables are set by this command (only used if + sql_command is SQLCOM_SET_OPTION) + @param query query + @param length query's length + @param charset charset which was used to encode this query +*/ + + +class Opt_trace_start { + public: + Opt_trace_start(THD *thd_arg, TABLE_LIST *tbl, + enum enum_sql_command sql_command, + List *set_vars, + const char *query, + size_t query_length, + const CHARSET_INFO *query_charset); + ~Opt_trace_start(); + + private: + Opt_trace_context *const ctx; + /* + True: the query will be traced + False: otherwise + */ + bool traceable; +}; + +/** + Prints SELECT query to optimizer trace. It is not the original query (as in + @c Opt_trace_context::set_query()) but a printout of the parse tree + (Item-s). + @param thd the THD + @param select_lex query's parse tree + @param trace_object Json_writer object to which the query will be added +*/ +void opt_trace_print_expanded_query(THD *thd, SELECT_LEX *select_lex, + Json_writer_object *trace_object); + +void add_table_scan_values_to_trace(THD *thd, JOIN_TAB *tab); + +/* + Security related (need to add a proper comment here) +*/ + +/** + If the security context is not that of the connected user, inform the trace + system that a privilege is missing. With one exception: see below. + + @param thd + + This serves to eliminate the following issue. + Any information readable by a SELECT may theoretically end up in + the trace. And a SELECT may read information from other places than tables: + - from views (reading their bodies) + - from stored routines (reading their bodies) + - from files (reading their content), with LOAD_FILE() + - from the list of connections (reading their queries...), with + I_S.PROCESSLIST. + If the connected user has EXECUTE privilege on a routine which does a + security context change, the routine can retrieve information internally + (if allowed by the SUID context's privileges), and present only a portion + of it to the connected user. But with tracing on, all information is + possibly in the trace. So the connected user receives more information than + the routine's definer intended to provide. Fixing this issue would require + adding, near many privilege checks in the server, a new + optimizer-trace-specific check done against the connected user's context, + to verify that the connected user has the right to see the retrieved + information. + + Instead, our chosen simpler solution is that if we see a security context + change where SUID user is not the connected user, we disable tracing. With + only one safe exception: if the connected user has all global privileges + (because then she/he can find any information anyway). By "all global + privileges" we mean everything but WITH GRANT OPTION (that latter one isn't + related to information gathering). + + Read access to I_S.OPTIMIZER_TRACE by another user than the connected user + is restricted: @see fill_optimizer_trace_info(). +*/ +void opt_trace_disable_if_no_security_context_access(THD *thd); + +void opt_trace_disable_if_no_tables_access(THD *thd, TABLE_LIST *tbl); + +/** + If tracing is on, checks additional privileges for a view, to make sure + that the user has the right to do SHOW CREATE VIEW. For that: + - this function checks SHOW VIEW + - SELECT is tested in opt_trace_disable_if_no_tables_access() + - SELECT + SHOW VIEW is sufficient for SHOW CREATE VIEW. + We also check underlying tables. + If a privilege is missing, notifies the trace system. + This function should be called when the view's underlying tables have not + yet been merged. + + @param thd THD context + @param view view to check + @param underlying_tables underlying tables/views of 'view' + */ + +void opt_trace_disable_if_no_view_access(THD *thd, TABLE_LIST *view, + TABLE_LIST *underlying_tables); + +/** + If tracing is on, checks additional privileges on a stored routine, to make + sure that the user has the right to do SHOW CREATE PROCEDURE/FUNCTION. For + that, we use the same checks as in those SHOW commands. + If a privilege is missing, notifies the trace system. + + This function is not redundant with + opt_trace_disable_if_no_security_context_access(). + Indeed, for a SQL SECURITY INVOKER routine, there is no context change, but + we must still verify that the invoker can do SHOW CREATE. + + For triggers, see note in sp_head::execute_trigger(). + + @param thd + @param sp routine to check + */ +void opt_trace_disable_if_no_stored_proc_func_access(THD *thd, sp_head *sp); + +/** + Fills information_schema.OPTIMIZER_TRACE with rows (one per trace) + @retval 0 ok + @retval 1 error +*/ +int fill_optimizer_trace_info(THD *thd, TABLE_LIST *tables, Item *); + +#define OPT_TRACE_TRANSFORM(writer, object_level0, object_level1, \ + select_number, from, to) \ + Json_writer_object object_level0(writer); \ + Json_writer_object object_level1(writer, "transformation"); \ + object_level1.add_select_number(select_number).add("from", from).add("to", to); +#endif \ No newline at end of file diff --git a/sql/opt_trace_context.h b/sql/opt_trace_context.h new file mode 100644 index 00000000000..87317f67e22 --- /dev/null +++ b/sql/opt_trace_context.h @@ -0,0 +1,92 @@ +#ifndef OPT_TRACE_CONTEXT_INCLUDED +#define OPT_TRACE_CONTEXT_INCLUDED + +#include "sql_array.h" + +class Opt_trace_stmt; + +class Opt_trace_context +{ +public: + Opt_trace_context(); + ~Opt_trace_context(); + + void start(THD *thd, TABLE_LIST *tbl, + enum enum_sql_command sql_command, + const char *query, + size_t query_length, + const CHARSET_INFO *query_charset, + ulong max_mem_size_arg); + void end(); + void set_query(const char *query, size_t length, const CHARSET_INFO *charset); + void flush_optimizer_trace(); + void set_allowed_mem_size(size_t mem_size); + size_t remaining_mem_size(); + +private: + Opt_trace_stmt* top_trace() + { + return *(traces->front()); + } + +public: + + /* + This returns the top trace from the list of traces. This function + is used when we want to see the contents of the INFORMATION_SCHEMA.OPTIMIZER_TRACE + table. + */ + + Opt_trace_stmt* get_top_trace() + { + if (!traces || !traces->elements()) + return NULL; + return top_trace(); + } + + /* + This returns the current trace, to which we are still writing and has not been finished + */ + + Json_writer* get_current_json(); + + bool empty() + { + return traces && (static_cast(traces->elements()) != 0); + } + + bool is_started() + { + return current_trace && is_enabled(); + } + + bool disable_tracing_if_required(); + + bool enable_tracing_if_required(); + + bool is_enabled(); + + void missing_privilege(); + + static const char *flag_names[]; + enum + { + FLAG_DEFAULT = 0, + FLAG_ENABLED = 1 << 0 + }; + +private: + /* + List of traces (currently it stores only 1 trace) + */ + Dynamic_array *traces; + Opt_trace_stmt *current_trace; + /* + TRUE: if we allocate memory for list of traces + FALSE: otherwise + */ + bool inited; + size_t max_mem_size; +}; + +#endif /* OPT_TRACE_CONTEXT_INCLUDED */ diff --git a/sql/set_var.h b/sql/set_var.h index 6097b28e76f..8a82e07fd6b 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -275,6 +275,10 @@ public: virtual int update(THD *thd)=0; /* To set the value */ virtual int light_check(THD *thd) { return check(thd); } /* for PS */ virtual bool is_system() { return FALSE; } + /** + @returns whether this variable is @@@@optimizer_trace. + */ + virtual bool is_var_optimizer_trace() const { return false; } }; @@ -306,6 +310,11 @@ public: int check(THD *thd); int update(THD *thd); int light_check(THD *thd); + virtual bool is_var_optimizer_trace() const + { + extern sys_var *Sys_optimizer_trace_ptr; + return var == Sys_optimizer_trace_ptr; + } }; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 8345a9efe61..11c1234e2db 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -29,6 +29,8 @@ #include "sql_derived.h" // mysql_handle_derived #include "sql_cte.h" #include "sql_select.h" // Virtual_tmp_table +#include "opt_trace.h" +#include "my_json_writer.h" #ifdef USE_PRAGMA_IMPLEMENTATION #pragma implementation @@ -1146,6 +1148,8 @@ sp_head::execute(THD *thd, bool merge_da_on_success) if (check_stack_overrun(thd, 7 * STACK_MIN_SIZE, (uchar*)&old_packet)) DBUG_RETURN(TRUE); + opt_trace_disable_if_no_security_context_access(thd); + /* init per-instruction memroot */ init_sql_alloc(&execute_mem_root, "per_instruction_memroot", MEM_ROOT_BLOCK_SIZE, 0, MYF(0)); @@ -1982,6 +1986,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, thd->variables.option_bits&= ~OPTION_BIN_LOG; } + opt_trace_disable_if_no_stored_proc_func_access(thd, this); /* Switch to call arena/mem_root so objects like sp_cursor or Item_cache holders for case expressions can be allocated on it. @@ -2272,6 +2277,7 @@ sp_head::execute_procedure(THD *thd, List *args) err_status= set_routine_security_ctx(thd, this, &save_security_ctx); #endif + opt_trace_disable_if_no_stored_proc_func_access(thd, this); if (!err_status) { err_status= execute(thd, TRUE); @@ -3297,6 +3303,13 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, thd->lex->safe_to_cache_query= 0; #endif + Opt_trace_start ots(thd, m_lex->query_tables, + SQLCOM_SELECT, &m_lex->var_list, + NULL, 0, + thd->variables.character_set_client); + + Json_writer_object trace_command(thd); + Json_writer_array trace_command_steps(thd, "steps"); if (open_tables) res= check_dependencies_in_with_clauses(m_lex->with_clauses_list) || instr->exec_open_and_lock_tables(thd, m_lex->query_tables); diff --git a/sql/sp_head.h b/sql/sp_head.h index 8db6ecac9e7..f59da93d8aa 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -2024,6 +2024,7 @@ private: }; // class sp_instr_set_case_expr : public sp_instr_opt_meta +bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access); #ifndef NO_EMBEDDED_ACCESS_CHECKS bool diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 81db3c286ad..97e3bde97dd 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -71,6 +71,7 @@ #include "wsrep_thd.h" #include "wsrep_trans_observer.h" #endif /* WITH_WSREP */ +#include "opt_trace.h" #ifdef HAVE_SYS_SYSCALL_H #include @@ -1410,6 +1411,7 @@ void THD::change_user(void) sp_cache_clear(&sp_func_cache); sp_cache_clear(&sp_package_spec_cache); sp_cache_clear(&sp_package_body_cache); + opt_trace.flush_optimizer_trace(); } /** @@ -2187,6 +2189,11 @@ void THD::reset_globals() net.thd= 0; } +bool THD::trace_started() +{ + return opt_trace.is_started(); +} + /* Cleanup after query. @@ -4337,6 +4344,13 @@ bool Security_context::set_user(char *user_arg) return user == 0; } +bool Security_context::check_access(ulong want_access, bool match_any) +{ + DBUG_ENTER("Security_context::check_access"); + DBUG_RETURN((match_any ? (master_access & want_access) + : ((master_access & want_access) == want_access))); +} + #ifndef NO_EMBEDDED_ACCESS_CHECKS /** Initialize this security context from the passed in credentials diff --git a/sql/sql_class.h b/sql/sql_class.h index 402a114aadd..d6da0566bbe 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -28,6 +28,7 @@ #include "rpl_tblmap.h" #include "mdl.h" #include "field.h" // Create_field +#include "opt_trace_context.h" #include "probes_mysql.h" #include "sql_locale.h" /* my_locale_st */ #include "sql_profile.h" /* PROFILING */ @@ -569,6 +570,8 @@ typedef struct system_variables ulonglong long_query_time; ulonglong max_statement_time; ulonglong optimizer_switch; + ulonglong optimizer_trace; + ulong optimizer_trace_max_mem_size; sql_mode_t sql_mode; ///< which non-standard SQL behaviour should be enabled sql_mode_t old_behavior; ///< which old SQL behaviour should be enabled ulonglong option_bits; ///< OPTION_xxx constants, e.g. OPTION_PROFILING @@ -1350,6 +1353,14 @@ public: restore_security_context(THD *thd, Security_context *backup); #endif bool user_matches(Security_context *); + /** + Check global access + @param want_access The required privileges + @param match_any if the security context must match all or any of the req. + * privileges. + @return True if the security context fulfills the access requirements. + */ + bool check_access(ulong want_access, bool match_any = false); }; @@ -2306,6 +2317,8 @@ public: Security_context main_security_ctx; Security_context *security_ctx; + Security_context *security_context() const { return security_ctx; } + void set_security_context(Security_context *sctx) { security_ctx = sctx; } /* Points to info-string that we show in SHOW PROCESSLIST @@ -2989,6 +3002,7 @@ public: ulonglong bytes_sent_old; ulonglong affected_rows; /* Number of changed rows */ + Opt_trace_context opt_trace; pthread_t real_id; /* For debugging */ my_thread_id thread_id, thread_dbug_id; uint32 os_thread_id; @@ -3297,6 +3311,7 @@ public: void reset_for_reuse(); bool store_globals(); void reset_globals(); + bool trace_started(); #ifdef SIGNAL_WITH_VIO_CLOSE inline void set_active_vio(Vio* vio) { diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 878aa715b84..28d28ca2425 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -32,6 +32,7 @@ #include "sql_acl.h" // SELECT_ACL #include "sql_class.h" #include "sql_cte.h" +#include "my_json_writer.h" typedef bool (*dt_processor)(THD *thd, LEX *lex, TABLE_LIST *derived); @@ -198,6 +199,7 @@ mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases) if ((res= (*processors[phase])(lex->thd, lex, derived))) break; } + lex->thd->derived_tables_processing= FALSE; DBUG_RETURN(res); } @@ -368,6 +370,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", (derived->alias.str ? derived->alias.str : ""), derived->get_unit())); + const char *cause= NULL; if (derived->merged) { @@ -379,6 +382,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) if (dt_select->uncacheable & UNCACHEABLE_RAND) { /* There is random function => fall back to materialization. */ + cause= "Random function in the select"; derived->change_refs_to_fields(); derived->set_materialized_derived(); DBUG_RETURN(FALSE); @@ -401,15 +405,11 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) and small subqueries, and the bigger one can't be merged it wouldn't block the smaller one. */ - if (parent_lex->get_free_table_map(&map, &tablenr)) - { - /* There is no enough table bits, fall back to materialization. */ - goto unconditional_materialization; - } - - if (dt_select->leaf_tables.elements + tablenr > MAX_TABLES) + if (parent_lex->get_free_table_map(&map, &tablenr) || + dt_select->leaf_tables.elements + tablenr > MAX_TABLES) { /* There is no enough table bits, fall back to materialization. */ + cause= "Not enough table bits to merge subquery"; goto unconditional_materialization; } @@ -486,6 +486,24 @@ exit_merge: DBUG_RETURN(res); unconditional_materialization: + + if (unlikely(thd->trace_started())) + { + /* + Add to the optimizer trace the change in choice for merged + derived tables/views to materialised ones. + */ + Json_writer_object trace_wrapper(thd); + Json_writer_object trace_derived(thd, derived->is_derived() ? + "derived" : "view"); + trace_derived.add("table", derived->alias.str ? derived->alias.str : "") + .add_select_number(derived->get_unit()-> + first_select()->select_number) + .add("initial_choice", "merged") + .add("final_choice", "materialized") + .add("cause", cause); + } + derived->change_refs_to_fields(); derived->set_materialized_derived(); if (!derived->table || !derived->table->is_created()) @@ -654,7 +672,6 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_ENTER("mysql_derived_prepare"); DBUG_PRINT("enter", ("unit: %p table_list: %p alias: '%s'", unit, derived, derived->alias.str)); - if (!unit) DBUG_RETURN(FALSE); @@ -747,6 +764,22 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) } } + if (unlikely(thd->trace_started())) + { + /* + Add to optimizer trace whether a derived table/view + is merged into the parent select or not. + */ + Json_writer_object trace_wrapper(thd); + Json_writer_object trace_derived(thd, derived->is_derived() ? + "derived" : "view"); + trace_derived.add("table", derived->alias.str ? derived->alias.str : "") + .add_select_number(derived->get_unit()->first_select()->select_number); + if (derived->is_materialized_derived()) + trace_derived.add("materialized", true); + if (derived->is_merged_derived()) + trace_derived.add("merged", true); + } /* Above cascade call of prepare is important for PS protocol, but after it is called we can check if we really need prepare for this derived diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 1c45b05ccc5..022a8beb6d6 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -233,7 +233,7 @@ void Explain_query::print_explain_json(select_result_sink *output, CHARSET_INFO *cs= system_charset_info; List item_list; - String *buf= &writer.output; + const String *buf= writer.output.get_string(); item_list.push_back(new (thd->mem_root) Item_string(thd, buf->ptr(), buf->length(), cs), thd->mem_root); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7b6029aaa12..25dfdbcbc71 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -100,6 +100,7 @@ #include "set_var.h" #include "sql_bootstrap.h" #include "sql_sequence.h" +#include "opt_trace.h" #include "my_json_writer.h" @@ -3412,6 +3413,13 @@ mysql_execute_command(THD *thd) #ifdef HAVE_REPLICATION } /* endif unlikely slave */ #endif + Opt_trace_start ots(thd, all_tables, lex->sql_command, &lex->var_list, + thd->query(), thd->query_length(), + thd->variables.character_set_client); + + Json_writer_object trace_command(thd); + Json_writer_array trace_command_steps(thd, "steps"); + #ifdef WITH_WSREP if (WSREP(thd)) { diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index c8cc64dba7e..6c3ad9c6924 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -112,6 +112,7 @@ When one supplies long data for a placeholder: #include "sp_cache.h" #include "sql_handler.h" // mysql_ha_rm_tables #include "probes_mysql.h" +#include "opt_trace.h" #ifdef EMBEDDED_LIBRARY /* include MYSQL_BIND headers */ #include @@ -2273,6 +2274,17 @@ static bool check_prepared_statement(Prepared_statement *stmt) lex->first_select_lex()->context.resolve_in_table_list_only(select_lex-> get_table_list()); + /* + For the optimizer trace, this is the symmetric, for statement preparation, + of what is done at statement execution (in mysql_execute_command()). + */ + Opt_trace_start ots(thd, tables, lex->sql_command, &lex->var_list, + thd->query(), thd->query_length(), + thd->variables.character_set_client); + + Json_writer_object trace_command(thd); + Json_writer_array trace_command_steps(thd, "steps"); + /* Reset warning count for each query that uses tables */ if (tables) thd->get_stmt_da()->opt_clear_warning_info(thd->query_id); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1478dd93af4..06205a46f40 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -64,6 +64,8 @@ #include "sys_vars_shared.h" #include "sp_head.h" #include "sp_rcontext.h" +#include "my_json_writer.h" +#include "opt_trace.h" /* A key part number that means we're using a fulltext scan. @@ -295,6 +297,8 @@ void set_postjoin_aggr_write_func(JOIN_TAB *tab); static Item **get_sargable_cond(JOIN *join, TABLE *table); +static void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables); + #ifndef DBUG_OFF /* @@ -345,6 +349,40 @@ bool dbug_user_var_equals_int(THD *thd, const char *name, int value) } #endif +static void trace_table_dependencies(THD *thd, + JOIN_TAB *join_tabs, uint table_count) +{ + Json_writer_object trace_wrapper(thd); + Json_writer_array trace_dep(thd, "table_dependencies"); + for (uint i = 0; i < table_count; i++) + { + TABLE_LIST *table_ref = join_tabs[i].tab_list; + Json_writer_object trace_one_table(thd); + trace_one_table.add_table_name(&join_tabs[i]); + trace_one_table.add("row_may_be_null", + (bool)table_ref->table->maybe_null); + const table_map map = table_ref->get_map(); + DBUG_ASSERT(map < (1ULL << table_count)); + for (uint j = 0; j < table_count; j++) + { + if (map & (1ULL << j)) + { + trace_one_table.add("map_bit", static_cast(j)); + break; + } + } + Json_writer_array depends_on(thd, "depends_on_map_bits"); + static_assert(sizeof(table_ref->get_map()) <= 64, + "RAND_TABLE_BIT may be in join_tabs[i].dependent, so we test " + "all 64 bits."); + for (uint j = 0; j < 64; j++) + { + if (join_tabs[i].dependent & (1ULL << j)) + depends_on.add(static_cast(j)); + } + } +} + /** This handles SELECT with and without UNION. @@ -994,6 +1032,11 @@ JOIN::prepare(TABLE_LIST *tables_init, join_list= &select_lex->top_join_list; union_part= unit_arg->is_unit_op(); + Json_writer_object trace_wrapper(thd); + Json_writer_object trace_prepare(thd, "join_preparation"); + trace_prepare.add_select_number(select_lex->select_number); + Json_writer_array trace_steps(thd, "steps"); + // simple check that we got usable conds dbug_print_item(conds); @@ -1336,6 +1379,11 @@ JOIN::prepare(TABLE_LIST *tables_init, } } + { + Json_writer_object trace_wrapper(thd); + opt_trace_print_expanded_query(thd, select_lex, &trace_wrapper); + } + if (!procedure && result && result->prepare(fields_list, unit_arg)) goto err; /* purecov: inspected */ @@ -1517,6 +1565,11 @@ JOIN::optimize_inner() set_allowed_join_cache_types(); need_distinct= TRUE; + Json_writer_object trace_wrapper(thd); + Json_writer_object trace_prepare(thd, "join_optimization"); + trace_prepare.add_select_number(select_lex->select_number); + Json_writer_array trace_steps(thd, "steps"); + /* Needed in case optimizer short-cuts, set properly in make_aggr_tables_info() @@ -3914,6 +3967,12 @@ void JOIN::exec_inner() limit in order to produce the partial query result stored in the UNION temp table. */ + + Json_writer_object trace_wrapper(thd); + Json_writer_object trace_exec(thd, "join_execution"); + trace_exec.add_select_number(select_lex->select_number); + Json_writer_array trace_steps(thd, "steps"); + if (!select_lex->outer_select() && // (1) select_lex != select_lex->master_unit()->fake_select_lex) // (2) thd->lex->set_limit_rows_examined(); @@ -4464,6 +4523,7 @@ make_join_statistics(JOIN *join, List &tables_list, SARGABLE_PARAM *sargables= 0; List_iterator ti(tables_list); TABLE_LIST *tables; + THD *thd= join->thd; DBUG_ENTER("make_join_statistics"); table_count=join->table_count; @@ -4659,9 +4719,12 @@ make_join_statistics(JOIN *join, List &tables_list, } } + if (thd->trace_started()) + trace_table_dependencies(thd, stat, join->table_count); + if (join->conds || outer_join) { - if (update_ref_and_keys(join->thd, keyuse_array, stat, join->table_count, + if (update_ref_and_keys(thd, keyuse_array, stat, join->table_count, join->conds, ~outer_join, join->select_lex, &sargables)) goto error; /* @@ -4673,10 +4736,12 @@ make_join_statistics(JOIN *join, List &tables_list, ((Item_in_subselect*)join->unit->item)->test_strategy(SUBS_IN_TO_EXISTS)); if (keyuse_array->elements && - sort_and_filter_keyuse(join->thd, keyuse_array, + sort_and_filter_keyuse(thd, keyuse_array, skip_unprefixed_keyparts)) goto error; DBUG_EXECUTE("opt", print_keyuse_array(keyuse_array);); + if (thd->trace_started()) + print_keyuse_array_for_trace(thd, keyuse_array); } join->const_table_map= no_rows_const_tables; @@ -4961,143 +5026,160 @@ make_join_statistics(JOIN *join, List &tables_list, /* Calc how many (possible) matched records in each table */ - for (s=stat ; s < stat_end ; s++) + /* + Todo: add a function so that we can add these Json_writer_objects + easily. + Another way would be to enclose them in a scope {}; + */ { - s->startup_cost= 0; - if (s->type == JT_SYSTEM || s->type == JT_CONST) + Json_writer_object rows_estimation_wrapper(thd); + Json_writer_array rows_estimation(thd, "rows_estimation"); + for (s=stat ; s < stat_end ; s++) { - /* Only one matching row */ - s->found_records= s->records= 1; - s->read_time=1.0; - s->worst_seeks=1.0; - continue; - } - /* Approximate found rows and time to read them */ - if (s->table->is_filled_at_execution()) - { - get_delayed_table_estimates(s->table, &s->records, &s->read_time, - &s->startup_cost); - s->found_records= s->records; - table->quick_condition_rows=s->records; - } - else - { - s->scan_time(); - } - - if (s->table->is_splittable()) - s->add_keyuses_for_splitting(); - - /* - Set a max range of how many seeks we can expect when using keys - This is can't be to high as otherwise we are likely to use - table scan. - */ - s->worst_seeks= MY_MIN((double) s->found_records / 10, - (double) s->read_time*3); - if (s->worst_seeks < 2.0) // Fix for small tables - s->worst_seeks=2.0; - - /* - Add to stat->const_keys those indexes for which all group fields or - all select distinct fields participate in one index. - */ - add_group_and_distinct_keys(join, s); - - s->table->cond_selectivity= 1.0; - - /* - Perform range analysis if there are keys it could use (1). - Don't do range analysis for materialized subqueries (2). - Don't do range analysis for materialized derived tables (3) - */ - if ((!s->const_keys.is_clear_all() || - !bitmap_is_clear_all(&s->table->cond_set)) && // (1) - !s->table->is_filled_at_execution() && // (2) - !(s->table->pos_in_table_list->derived && // (3) - s->table->pos_in_table_list->is_materialized_derived())) // (3) - { - bool impossible_range= FALSE; - ha_rows records= HA_POS_ERROR; - SQL_SELECT *select= 0; - Item **sargable_cond= NULL; - if (!s->const_keys.is_clear_all()) + s->startup_cost= 0; + if (s->type == JT_SYSTEM || s->type == JT_CONST) { - sargable_cond= get_sargable_cond(join, s->table); - select= make_select(s->table, found_const_table_map, - found_const_table_map, - *sargable_cond, - (SORT_INFO*) 0, - 1, &error); - if (!select) - goto error; - records= get_quick_record_count(join->thd, select, s->table, - &s->const_keys, join->row_limit); - - /* - Range analyzer might have modified the condition. Put it the new - condition to where we got it from. - */ - *sargable_cond= select->cond; - - s->quick=select->quick; - s->needed_reg=select->needed_reg; - select->quick=0; - impossible_range= records == 0 && s->table->reginfo.impossible_range; + Json_writer_object table_records(thd); + /* Only one matching row */ + s->found_records= s->records= 1; + s->read_time=1.0; + s->worst_seeks=1.0; + table_records.add_table_name(s) + .add("rows", s->found_records) + .add("cost", s->read_time) + .add("table_type", s->type == JT_CONST ? + "const" : + "system"); + continue; } - if (!impossible_range) + /* Approximate found rows and time to read them */ + if (s->table->is_filled_at_execution()) { - if (!sargable_cond) + get_delayed_table_estimates(s->table, &s->records, &s->read_time, + &s->startup_cost); + s->found_records= s->records; + table->quick_condition_rows=s->records; + } + else + s->scan_time(); + + if (s->table->is_splittable()) + s->add_keyuses_for_splitting(); + + /* + Set a max range of how many seeks we can expect when using keys + This is can't be to high as otherwise we are likely to use + table scan. + */ + s->worst_seeks= MY_MIN((double) s->found_records / 10, + (double) s->read_time*3); + if (s->worst_seeks < 2.0) // Fix for small tables + s->worst_seeks=2.0; + + /* + Add to stat->const_keys those indexes for which all group fields or + all select distinct fields participate in one index. + */ + add_group_and_distinct_keys(join, s); + + s->table->cond_selectivity= 1.0; + + /* + Perform range analysis if there are keys it could use (1). + Don't do range analysis for materialized subqueries (2). + Don't do range analysis for materialized derived tables (3) + */ + if ((!s->const_keys.is_clear_all() || + !bitmap_is_clear_all(&s->table->cond_set)) && // (1) + !s->table->is_filled_at_execution() && // (2) + !(s->table->pos_in_table_list->derived && // (3) + s->table->pos_in_table_list->is_materialized_derived())) // (3) + { + bool impossible_range= FALSE; + ha_rows records= HA_POS_ERROR; + SQL_SELECT *select= 0; + Item **sargable_cond= NULL; + if (!s->const_keys.is_clear_all()) + { sargable_cond= get_sargable_cond(join, s->table); - if (join->thd->variables.optimizer_use_condition_selectivity > 1) - calculate_cond_selectivity_for_table(join->thd, s->table, - sargable_cond); - if (s->table->reginfo.impossible_range) - { - impossible_range= TRUE; - records= 0; + + select= make_select(s->table, found_const_table_map, + found_const_table_map, + *sargable_cond, + (SORT_INFO*) 0, 1, &error); + if (!select) + goto error; + records= get_quick_record_count(join->thd, select, s->table, + &s->const_keys, join->row_limit); + + /* + Range analyzer might have modified the condition. Put it the new + condition to where we got it from. + */ + *sargable_cond= select->cond; + + s->quick=select->quick; + s->needed_reg=select->needed_reg; + select->quick=0; + impossible_range= records == 0 && s->table->reginfo.impossible_range; } - } - if (impossible_range) - { - /* - Impossible WHERE or ON expression - In case of ON, we mark that the we match one empty NULL row. - In case of WHERE, don't set found_const_table_map to get the - caller to abort with a zero row result. - */ - TABLE_LIST *emb= s->table->pos_in_table_list->embedding; - if (emb && !emb->sj_on_expr) + if (!impossible_range) { - /* Mark all tables in a multi-table join nest as const */ - mark_join_nest_as_const(join, emb, &found_const_table_map, - &const_count); - } - else - { - join->const_table_map|= s->table->map; - set_position(join,const_count++,s,(KEYUSE*) 0); - s->type= JT_CONST; - s->table->const_table= 1; - if (*s->on_expr_ref) + if (!sargable_cond) + sargable_cond= get_sargable_cond(join, s->table); + if (join->thd->variables.optimizer_use_condition_selectivity > 1) + calculate_cond_selectivity_for_table(join->thd, s->table, + sargable_cond); + if (s->table->reginfo.impossible_range) { - /* Generate empty row */ - s->info= ET_IMPOSSIBLE_ON_CONDITION; - found_const_table_map|= s->table->map; - mark_as_null_row(s->table); // All fields are NULL + impossible_range= TRUE; + records= 0; } } + if (impossible_range) + { + /* + Impossible WHERE or ON expression + In case of ON, we mark that the we match one empty NULL row. + In case of WHERE, don't set found_const_table_map to get the + caller to abort with a zero row result. + */ + TABLE_LIST *emb= s->table->pos_in_table_list->embedding; + if (emb && !emb->sj_on_expr) + { + /* Mark all tables in a multi-table join nest as const */ + mark_join_nest_as_const(join, emb, &found_const_table_map, + &const_count); + } + else + { + join->const_table_map|= s->table->map; + set_position(join,const_count++,s,(KEYUSE*) 0); + s->type= JT_CONST; + s->table->const_table= 1; + if (*s->on_expr_ref) + { + /* Generate empty row */ + s->info= ET_IMPOSSIBLE_ON_CONDITION; + found_const_table_map|= s->table->map; + mark_as_null_row(s->table); // All fields are NULL + } + } + } + if (records != HA_POS_ERROR) + { + s->found_records=records; + s->read_time= s->quick ? s->quick->read_time : 0.0; + } + if (select) + delete select; + else + add_table_scan_values_to_trace(thd, s); } - if (records != HA_POS_ERROR) - { - s->found_records=records; - s->read_time= s->quick ? s->quick->read_time : 0.0; - } - if (select) - delete select; + else + add_table_scan_values_to_trace(thd, s); } - } if (pull_out_semijoin_tables(join)) @@ -6856,11 +6938,15 @@ best_access_path(JOIN *join, MY_BITMAP *eq_join_set= &s->table->eq_join_set; KEYUSE *hj_start_key= 0; SplM_plan_info *spl_plan= 0; + const char* cause= NULL; disable_jbuf= disable_jbuf || idx == join->const_tables; Loose_scan_opt loose_scan_opt; DBUG_ENTER("best_access_path"); + + Json_writer_object trace_wrapper(thd, "best_access_path"); + Json_writer_array trace_paths(thd, "considered_access_paths"); bitmap_clear_all(eq_join_set); @@ -6975,6 +7061,7 @@ best_access_path(JOIN *join, if (rec < MATCHING_ROWS_IN_OTHER_TABLE) rec= MATCHING_ROWS_IN_OTHER_TABLE; // Fix for small tables + Json_writer_object trace_access_idx(thd); /* ft-keys require special treatment */ @@ -6986,6 +7073,8 @@ best_access_path(JOIN *join, */ tmp= prev_record_reads(join->positions, idx, found_ref); records= 1.0; + trace_access_idx.add("access_type", "fulltext") + .add("index", keyinfo->name); } else { @@ -7000,11 +7089,15 @@ best_access_path(JOIN *join, if ((key_flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME || MY_TEST(key_flags & HA_EXT_NOSAME)) { + trace_access_idx.add("access_type", "eq_ref") + .add("index", keyinfo->name); tmp = prev_record_reads(join->positions, idx, found_ref); records=1.0; } else { + trace_access_idx.add("access_type", "ref") + .add("index", keyinfo->name); if (!found_ref) { /* We found a const key */ /* @@ -7025,11 +7118,16 @@ best_access_path(JOIN *join, empty interval we wouldn't have got here). */ if (table->quick_keys.is_set(key)) + { records= (double) table->quick_rows[key]; + trace_access_idx.add("used_range_estimates", true); + } else { /* quick_range couldn't use key! */ records= (double) s->records/rec; + trace_access_idx.add("used_range_estimates", false) + .add("cause", "not available"); } } else @@ -7061,7 +7159,23 @@ best_access_path(JOIN *join, table->quick_n_ranges[key] == 1 && records > (double) table->quick_rows[key]) { + records= (double) table->quick_rows[key]; + trace_access_idx.add("used_range_estimates", true); + } + else + { + if (table->quick_keys.is_set(key)) + { + trace_access_idx.add("used_range_estimates",false) + .add("cause", + "not better than ref estimates"); + } + else + { + trace_access_idx.add("used_range_estimates", false) + .add("cause", "not available"); + } } } /* Limit the number of matched rows */ @@ -7077,6 +7191,9 @@ best_access_path(JOIN *join, } else { + trace_access_idx.add("access_type", + ref_or_null_part ? "ref_or_null" : "ref") + .add("index", keyinfo->name); /* Use as much key-parts as possible and a uniq key is better than a not unique key @@ -7131,6 +7248,7 @@ best_access_path(JOIN *join, table->quick_n_ranges[key] == 1 + MY_TEST(ref_or_null_part)) //(C3) { tmp= records= (double) table->quick_rows[key]; + trace_access_idx.add("used_range_estimates", true); } else { @@ -7156,7 +7274,19 @@ best_access_path(JOIN *join, if (!found_ref && table->quick_keys.is_set(key) && // (1) table->quick_key_parts[key] > max_key_part && // (2) records < (double)table->quick_rows[key]) // (3) + { + trace_access_idx.add("used_range_estimates", true); records= (double)table->quick_rows[key]; + } + else + { + if (table->quick_keys.is_set(key) && + table->quick_key_parts[key] < max_key_part) + { + trace_access_idx.add("chosen", false); + cause= "range uses more keyparts"; + } + } tmp= records; } @@ -7240,15 +7370,22 @@ best_access_path(JOIN *join, tmp*= record_count; } else + { + if (!(found_part & 1)) + cause= "no predicate for first keypart"; tmp= best_time; // Do nothing + } } tmp += s->startup_cost; loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp); } /* not ft_key */ + trace_access_idx.add("rows", records).add("cost", tmp); + if (tmp + 0.0001 < best_time - records/(double) TIME_FOR_COMPARE) { + trace_access_idx.add("chosen", true); best_time= tmp + records/(double) TIME_FOR_COMPARE; best= tmp; best_records= records; @@ -7256,6 +7393,12 @@ best_access_path(JOIN *join, best_max_key_part= max_key_part; best_ref_depends_map= found_ref; } + else + { + trace_access_idx.add("chosen", false) + .add("cause", cause ? cause : "cost"); + } + cause= NULL; } /* for each key */ records= best_records; } @@ -7277,6 +7420,7 @@ best_access_path(JOIN *join, (!(s->table->map & join->outer_join) || join->allowed_outer_join_with_cache)) // (2) { + Json_writer_object trace_access_hash(thd); double join_sel= 0.1; /* Estimate the cost of the hash join access to the table */ double rnd_records= matching_candidates_in_table(s, found_constraint, @@ -7296,7 +7440,12 @@ best_access_path(JOIN *join, best_key= hj_start_key; best_ref_depends_map= 0; best_uses_jbuf= TRUE; - } + trace_access_hash.add("type", "hash"); + trace_access_hash.add("index", "hj-key"); + trace_access_hash.add("cost", rnd_records); + trace_access_hash.add("cost", best); + trace_access_hash.add("chosen", true); + } /* Don't test table scan if it can't be better. @@ -7331,6 +7480,7 @@ best_access_path(JOIN *join, can be [considered to be] more expensive, which causes lookups not to be used for cases with small datasets, which is annoying. */ + Json_writer_object trace_access_scan(thd); if ((records >= s->found_records || best > s->read_time) && // (1) !(s->quick && best_key && s->quick->index == best_key->key && // (2) best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2) @@ -7350,6 +7500,10 @@ best_access_path(JOIN *join, if (s->quick) { + trace_access_scan.add("access_type", "range"); + /* + should have some info about all the different QUICK_SELECT + */ /* For each record we: - read record range through 'quick' @@ -7367,6 +7521,7 @@ best_access_path(JOIN *join, } else { + trace_access_scan.add("access_type", "scan"); /* Estimate cost of reading table. */ if (s->table->force_index && !best_key) // index scan tmp= s->table->file->read_time(s->ref.key, 1, s->records); @@ -7411,6 +7566,8 @@ best_access_path(JOIN *join, as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus tmp give us total cost of using TABLE SCAN */ + trace_access_scan.add("resulting_rows", rnd_records); + trace_access_scan.add("cost", tmp); if (best == DBL_MAX || (tmp + record_count/(double) TIME_FOR_COMPARE*rnd_records < (best_key->is_for_hash_join() ? best_time : @@ -7429,6 +7586,13 @@ best_access_path(JOIN *join, join->outer_join))); spl_plan= 0; } + trace_access_scan.add("chosen", best_key == NULL); + } + else + { + trace_access_scan.add("type", "scan"); + trace_access_scan.add("chosen", false); + trace_access_scan.add("cause", "cost"); } /* Update the cost information for the current partial plan */ @@ -7447,7 +7611,10 @@ best_access_path(JOIN *join, idx == join->const_tables && s->table == join->sort_by_table && join->unit->select_limit_cnt >= records) + { + trace_access_scan.add("use_tmp_table", true); join->sort_by_table= (TABLE*) 1; // Must use temporary table + } DBUG_VOID_RETURN; } @@ -7590,6 +7757,7 @@ choose_plan(JOIN *join, table_map join_tables) uint use_cond_selectivity= join->thd->variables.optimizer_use_condition_selectivity; bool straight_join= MY_TEST(join->select_options & SELECT_STRAIGHT_JOIN); + THD *thd= join->thd; DBUG_ENTER("choose_plan"); join->cur_embedding_map= 0; @@ -7626,6 +7794,9 @@ choose_plan(JOIN *join, table_map join_tables) join->table_count - join->const_tables, sizeof(JOIN_TAB*), jtab_sort_func, (void*)join->emb_sjm_nest); + Json_writer_object wrapper(thd); + Json_writer_array trace_plan(thd,"considered_execution_plans"); + if (!join->emb_sjm_nest) { choose_initial_table_order(join); @@ -7919,9 +8090,16 @@ optimize_straight_join(JOIN *join, table_map join_tables) uint use_cond_selectivity= join->thd->variables.optimizer_use_condition_selectivity; POSITION loose_scan_pos; + THD *thd= join->thd; for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++) { + Json_writer_object trace_one_table(thd); + if (unlikely(thd->trace_started())) + { + trace_plan_prefix(join, idx, join_tables); + trace_one_table.add_table_name(s); + } /* Find the best access method from 's' to the current partial plan */ best_access_path(join, s, join_tables, idx, disable_jbuf, record_count, join->positions + idx, &loose_scan_pos); @@ -8650,6 +8828,18 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, } +static void trace_plan_prefix(JOIN *join, uint idx, table_map remaining_tables) +{ + THD *const thd = join->thd; + Json_writer_array plan_prefix(thd, "plan_prefix"); + for (uint i = 0; i < idx; i++) + { + TABLE_LIST *const tr = join->positions[i].table->tab_list; + if (!(tr->map & remaining_tables)) + plan_prefix.add_table_name(join->positions[i].table); + } +} + /** Find a good, possibly optimal, query execution plan (QEP) by a possibly exhaustive search. @@ -8827,6 +9017,13 @@ best_extension_by_limited_search(JOIN *join, double current_record_count, current_read_time; POSITION *position= join->positions + idx; + Json_writer_object trace_one_table(thd); + if (unlikely(thd->trace_started())) + { + trace_plan_prefix(join, idx, remaining_tables); + trace_one_table.add_table_name(s); + } + /* Find the best access method from 's' to the current partial plan */ POSITION loose_scan_pos; best_access_path(join, s, remaining_tables, idx, disable_jbuf, @@ -8840,6 +9037,9 @@ best_extension_by_limited_search(JOIN *join, current_read_time=read_time + position->read_time + current_record_count / (double) TIME_FOR_COMPARE; + /* + TODO add filtering estimates here + */ advance_sj_state(join, remaining_tables, idx, ¤t_record_count, ¤t_read_time, &loose_scan_pos); @@ -8851,6 +9051,7 @@ best_extension_by_limited_search(JOIN *join, read_time, current_read_time, "prune_by_cost");); + trace_one_table.add("pruned_by_cost", true); restore_prev_nj_state(s); restore_prev_sj_state(remaining_tables, s, idx); continue; @@ -8884,6 +9085,7 @@ best_extension_by_limited_search(JOIN *join, read_time, current_read_time, "pruned_by_heuristic");); + trace_one_table.add("pruned_by_heuristic", true); restore_prev_nj_state(s); restore_prev_sj_state(remaining_tables, s, idx); continue; @@ -8901,6 +9103,7 @@ best_extension_by_limited_search(JOIN *join, if ( (search_depth > 1) && (remaining_tables & ~real_table_bit) & allowed_tables ) { /* Recursively expand the current partial plan */ swap_variables(JOIN_TAB*, join->best_ref[idx], *pos); + Json_writer_array trace_rest(thd, "rest_of_plan"); if (best_extension_by_limited_search(join, remaining_tables & ~real_table_bit, idx + 1, @@ -10502,23 +10705,40 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) there inside the triggers. */ { // Check const tables - join->exec_const_cond= - make_cond_for_table(thd, cond, + Item* const_cond= NULL; + const_cond= make_cond_for_table(thd, cond, join->const_table_map, (table_map) 0, -1, FALSE, FALSE); /* Add conditions added by add_not_null_conds(). */ for (uint i= 0 ; i < join->const_tables ; i++) - add_cond_and_fix(thd, &join->exec_const_cond, + add_cond_and_fix(thd, &const_cond, join->join_tab[i].select_cond); - DBUG_EXECUTE("where",print_where(join->exec_const_cond,"constants", + DBUG_EXECUTE("where",print_where(const_cond,"constants", QT_ORDINARY);); - if (join->exec_const_cond && !join->exec_const_cond->is_expensive() && - !join->exec_const_cond->val_int()) + + if (const_cond) { - DBUG_PRINT("info",("Found impossible WHERE condition")); - join->exec_const_cond= NULL; - DBUG_RETURN(1); // Impossible const condition + Json_writer_object trace_const_cond(thd); + trace_const_cond.add("condition_on_constant_tables", const_cond); + if (const_cond->is_expensive()) + { + trace_const_cond.add("evalualted", "false") + .add("cause", "expensive cond"); + } + else + { + const bool const_cond_result = const_cond->val_int() != 0; + if (!const_cond_result) + { + DBUG_PRINT("info",("Found impossible WHERE condition")); + trace_const_cond.add("evalualted", "true") + .add("found", "impossible where"); + join->exec_const_cond= NULL; + DBUG_RETURN(1); + } + } + join->exec_const_cond= const_cond; } if (join->table_count != join->const_tables) @@ -10555,6 +10775,11 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) /* Step #2: Extract WHERE/ON parts */ + Json_writer_object trace_wrapper(thd); + Json_writer_object trace_conditions(thd, "attaching_conditions_to_tables"); + trace_conditions.add("original_condition", cond); + Json_writer_array trace_attached_comp(thd, + "attached_conditions_computation"); uint i; for (i= join->top_join_tab_count - 1; i >= join->const_tables; i--) { @@ -10617,10 +10842,19 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) (!is_hash_join_key_no(tab->ref.key) && tab->table->intersect_keys.is_set(tab->ref.key)))) { - /* Range uses longer key; Use this instead of ref on key */ - tab->type=JT_ALL; - use_quick_range=1; - tab->use_quick=1; + /* Range uses longer key; Use this instead of ref on key */ + + /* + We can trace here, changing ref access to range access here + have a range that uses longer key. + Lets take @spetrunia's opinion + */ + Json_writer_object ref_to_range(thd); + ref_to_range.add("ref_to_range", true); + ref_to_range.add("cause", "range uses longer key"); + tab->type=JT_ALL; + use_quick_range=1; + tab->use_quick=1; tab->ref.key= -1; tab->ref.key_parts=0; // Don't use ref key. join->best_positions[i].records_read= rows2double(tab->quick->records); @@ -11058,6 +11292,20 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) if (!tab->bush_children) i++; } + + trace_attached_comp.end(); + Json_writer_array trace_attached_summary(thd, + "attached_conditions_summary"); + for (tab= first_depth_first_tab(join); tab; + tab= next_depth_first_tab(join, tab)) + { + if (!tab->table) + continue; + Item *const cond = tab->select_cond; + Json_writer_object trace_one_table(thd); + trace_one_table.add_table_name(tab); + trace_one_table.add("attached", cond); + } } DBUG_RETURN(0); } @@ -15983,12 +16231,24 @@ optimize_cond(JOIN *join, COND *conds, that occurs in a function set a pointer to the multiple equality predicate. Substitute a constant instead of this field if the multiple equality contains a constant. - */ + */ + + Json_writer_object trace_wrapper(thd); + Json_writer_object trace_cond(thd, "condition_processing"); + trace_cond.add("condition", join->conds == conds ? "WHERE" : "HAVING") + .add("original_condition", conds); + + Json_writer_array trace_steps(thd, "steps"); DBUG_EXECUTE("where", print_where(conds, "original", QT_ORDINARY);); conds= build_equal_items(join, conds, NULL, join_list, ignore_on_conds, cond_equal, MY_TEST(flags & OPT_LINK_EQUAL_FIELDS)); DBUG_EXECUTE("where",print_where(conds,"after equal_items", QT_ORDINARY);); + { + Json_writer_object equal_prop_wrapper(thd); + equal_prop_wrapper.add("transformation", "equality_propagation") + .add("resulting_condition", conds); + } /* change field = field to field = const for each found field = const */ propagate_cond_constants(thd, (I_List *) 0, conds, conds); @@ -15997,10 +16257,21 @@ optimize_cond(JOIN *join, COND *conds, Remove all and-levels where CONST item != CONST item */ DBUG_EXECUTE("where",print_where(conds,"after const change", QT_ORDINARY);); + { + Json_writer_object const_prop_wrapper(thd); + const_prop_wrapper.add("transformation", "constant_propagation") + .add("resulting_condition", conds); + } conds= conds->remove_eq_conds(thd, cond_value, true); if (conds && conds->type() == Item::COND_ITEM && ((Item_cond*) conds)->functype() == Item_func::COND_AND_FUNC) *cond_equal= &((Item_cond_and*) conds)->m_cond_equal; + + { + Json_writer_object cond_removal_wrapper(thd); + cond_removal_wrapper.add("transformation", "trivial_condition_removal") + .add("resulting_condition", conds); + } DBUG_EXECUTE("info",print_where(conds,"after remove", QT_ORDINARY);); } DBUG_RETURN(conds); @@ -26122,7 +26393,8 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str, // A view if (!(belong_to_view && - belong_to_view->compact_view_format)) + belong_to_view->compact_view_format) && + !(query_type & QT_ITEM_IDENT_SKIP_DB_NAMES)) { append_identifier(thd, str, &view_db); str->append('.'); @@ -26151,7 +26423,8 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str, // A normal table if (!(belong_to_view && - belong_to_view->compact_view_format)) + belong_to_view->compact_view_format) && + !(query_type & QT_ITEM_IDENT_SKIP_DB_NAMES)) { append_identifier(thd, str, &db); str->append('.'); @@ -26886,6 +27159,12 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, bool group= join && join->group && order == join->group_list; ha_rows refkey_rows_estimate= table->quick_condition_rows; const bool has_limit= (select_limit_arg != HA_POS_ERROR); + THD* thd= join ? join->thd : table->in_use; + + Json_writer_object trace_wrapper(thd); + Json_writer_object trace_cheaper_ordering( + thd, "reconsidering_access_paths_for_index_ordering"); + trace_cheaper_ordering.add("clause", group ? "GROUP BY" : "ORDER BY"); /* If not used with LIMIT, only use keys if the whole query can be @@ -26924,11 +27203,12 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, else read_time= table->file->scan_time(); + trace_cheaper_ordering.add("fanout", fanout); /* TODO: add cost of sorting here. */ read_time += COST_EPS; - + trace_cheaper_ordering.add("read_time", read_time); /* Calculate the selectivity of the ref_key for REF_ACCESS. For RANGE_ACCESS we use table->quick_condition_rows. @@ -26945,11 +27225,20 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, set_if_bigger(refkey_rows_estimate, 1); } + if (tab) + trace_cheaper_ordering.add_table_name(tab); + else + trace_cheaper_ordering.add_table_name(table); + trace_cheaper_ordering.add("rows_estimation", refkey_rows_estimate); + + Json_writer_array possible_keys(thd,"possible_keys"); for (nr=0; nr < table->s->keys ; nr++) { int direction; ha_rows select_limit= select_limit_arg; uint used_key_parts= 0; + Json_writer_object possible_key(thd); + possible_key.add("index", table->key_info[nr].name); if (keys.is_set(nr) && (direction= test_if_order_by_key(join, order, table, nr, @@ -26962,6 +27251,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, */ DBUG_ASSERT (ref_key != (int) nr); + possible_key.add("can_resolve_order", true); bool is_covering= (table->covering_keys.is_set(nr) || (table->file->index_flags(nr, 0, 1) & HA_CLUSTERED_INDEX)); @@ -27092,6 +27382,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, select_limit= (ha_rows) (select_limit * (double) table_records / refkey_rows_estimate); + possible_key.add("updated_limit", select_limit); rec_per_key= keyinfo->actual_rec_per_key(keyinfo->user_defined_key_parts-1); set_if_bigger(rec_per_key, 1); /* @@ -27111,9 +27402,11 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, if (get_range_limit_read_cost(tab, table, table_records, nr, select_limit, &range_scan_time)) { + possible_key.add("range_scan_time", range_scan_time); if (range_scan_time < index_scan_time) index_scan_time= range_scan_time; } + possible_key.add("index_scan_time", index_scan_time); if ((ref_key < 0 && (group || table->force_index || is_covering)) || index_scan_time < read_time) @@ -27124,17 +27417,29 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, table->covering_keys.is_set(ref_key)) ? refkey_rows_estimate : HA_POS_ERROR; - if ((is_best_covering && !is_covering) || - (is_covering && refkey_select_limit < select_limit)) + if (is_best_covering && !is_covering) + { + possible_key.add("chosen", false); + possible_key.add("cause", "covering index already found"); continue; + } + + if (is_covering && refkey_select_limit < select_limit) + { + possible_key.add("chosen", false); + possible_key.add("cause", "ref estimates better"); + continue; + } if (table->quick_keys.is_set(nr)) quick_records= table->quick_rows[nr]; + possible_key.add("records", quick_records); if (best_key < 0 || (select_limit <= MY_MIN(quick_records,best_records) ? keyinfo->user_defined_key_parts < best_key_parts : quick_records < best_records) || (!is_best_covering && is_covering)) { + possible_key.add("chosen", true); best_key= nr; best_key_parts= keyinfo->user_defined_key_parts; if (saved_best_key_parts) @@ -27144,8 +27449,47 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, best_key_direction= direction; best_select_limit= select_limit; } + else + { + char const *cause; + possible_key.add("chosen", false); + if (is_covering) + cause= "covering index already found"; + else + { + if (select_limit <= MY_MIN(quick_records,best_records)) + cause= "keyparts greater than the current best keyparts"; + else + cause= "rows estimation greater"; + } + possible_key.add("cause", cause); + } + } + else + { + possible_key.add("usable", false); + possible_key.add("cause", "cost"); } - } + } + else + { + possible_key.add("usable", false); + if (!group && select_limit == HA_POS_ERROR) + possible_key.add("cause", "order by without limit"); + } + } + else + { + if (keys.is_set(nr)) + { + possible_key.add("can_resolve_order", false); + possible_key.add("cause", "order can not be resolved by key"); + } + else + { + possible_key.add("can_resolve_order", false); + possible_key.add("cause", "not usable index for the query"); + } } } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3d2723081a3..80884d66590 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -63,6 +63,7 @@ #include "ha_partition.h" #endif #include "transaction.h" +#include "opt_trace.h" enum enum_i_s_events_fields { @@ -9764,6 +9765,10 @@ ST_FIELD_INFO check_constraints_fields_info[]= OPEN_FULL_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; + +/** For creating fields of information_schema.OPTIMIZER_TRACE */ +extern ST_FIELD_INFO optimizer_trace_info[]; + /* Description of ST_FIELD_INFO in table.h @@ -9816,6 +9821,8 @@ ST_SCHEMA_TABLE schema_tables[]= OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, {"OPEN_TABLES", open_tables_fields_info, 0, fill_open_tables, make_old_format, 0, -1, -1, 1, 0}, + {"OPTIMIZER_TRACE", optimizer_trace_info, 0, + fill_optimizer_trace_info, NULL, NULL, -1, -1, false, 0}, {"PARAMETERS", parameters_fields_info, 0, fill_schema_proc, 0, 0, -1, -1, 0, 0}, {"PARTITIONS", partitions_fields_info, 0, diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 3d43c35177d..f247fb10f89 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -24,6 +24,7 @@ #include "sql_show.h" // calc_sum_of_all_status #include "sql_select.h" #include "keycaches.h" +#include "my_json_writer.h" #include #include #if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_H) @@ -36,6 +37,8 @@ #include "events.h" #endif +#define FT_KEYPART (MAX_FIELDS+10) + static const char *lock_descriptions[] = { /* TL_UNLOCK */ "No lock", @@ -225,8 +228,6 @@ TEST_join(JOIN *join) } -#define FT_KEYPART (MAX_FIELDS+10) - static void print_keyuse(KEYUSE *keyuse) { char buff[256]; @@ -263,7 +264,6 @@ void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array) DBUG_UNLOCK_FILE; } - /* Print the current state during query optimization. @@ -655,3 +655,24 @@ Memory allocated by threads: %s\n", puts(""); fflush(stdout); } + +void print_keyuse_array_for_trace(THD *thd, DYNAMIC_ARRAY *keyuse_array) +{ + Json_writer_object wrapper(thd); + Json_writer_array trace_key_uses(thd, "ref_optimizer_key_uses"); + for(uint i=0; i < keyuse_array->elements; i++) + { + KEYUSE *keyuse= (KEYUSE*)dynamic_array_ptr(keyuse_array, i); + Json_writer_object keyuse_elem(thd); + keyuse_elem.add_table_name(keyuse->table->reginfo.join_tab); + keyuse_elem.add("field", (keyuse->keypart == FT_KEYPART) ? "" + : (keyuse->is_for_hash_join() + ? keyuse->table->field[keyuse->keypart] + ->field_name.str + : keyuse->table->key_info[keyuse->key] + .key_part[keyuse->keypart] + .field->field_name.str)); + keyuse_elem.add("equals",keyuse->val); + keyuse_elem.add("null_rejecting",keyuse->null_rejecting); + } +} diff --git a/sql/sql_test.h b/sql/sql_test.h index 867582a9569..cbef581b784 100644 --- a/sql/sql_test.h +++ b/sql/sql_test.h @@ -17,6 +17,7 @@ #define SQL_TEST_INCLUDED #include "mysqld.h" +#include "opt_trace_context.h" class JOIN; struct TABLE_LIST; @@ -34,6 +35,7 @@ void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array); void print_sjm(SJ_MATERIALIZATION_INFO *sjm); void dump_TABLE_LIST_graph(SELECT_LEX *select_lex, TABLE_LIST* tl); #endif +void print_keyuse_array_for_trace(THD *thd, DYNAMIC_ARRAY *keyuse_array); void mysql_print_status(); #endif /* SQL_TEST_INCLUDED */ diff --git a/sql/sql_view.cc b/sql/sql_view.cc index e475a3d3719..31032c5cd5e 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -36,6 +36,7 @@ #include "datadict.h" // dd_frm_is_view() #include "sql_derived.h" #include "sql_cte.h" // check_dependencies_in_with_clauses() +#include "opt_trace.h" #define MD5_BUFF_LENGTH 33 @@ -1419,6 +1420,15 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, if (check_dependencies_in_with_clauses(thd->lex->with_clauses_list)) goto err; + /* + Check rights to run commands which show underlying tables. + In the optimizer trace we would not like to show trace for + cases when the current user does not have rights for the + underlying tables. + */ + if (!table->prelocking_placeholder) + opt_trace_disable_if_no_view_access(thd, table, view_tables); + /* Check rights to run commands (ANALYZE SELECT, EXPLAIN SELECT & SHOW CREATE) which show underlying tables. diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 7241685fb61..a8b557c90c8 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -53,6 +53,7 @@ #include #include "debug_sync.h" // DEBUG_SYNC #include "sql_show.h" +#include "opt_trace_context.h" #include "log_event.h" #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE @@ -2542,6 +2543,23 @@ static Sys_var_flagset Sys_optimizer_switch( NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_optimizer_switch)); +static Sys_var_flagset Sys_optimizer_trace( + "optimizer_trace", + "Controls tracing of the Optimizer:" + " optimizer_trace=option=val[,option=val...], where option is one of" + " {enabled}" + " and val is one of {on, off, default}", + SESSION_VAR(optimizer_trace), CMD_LINE(REQUIRED_ARG), + Opt_trace_context::flag_names, DEFAULT(Opt_trace_context::FLAG_DEFAULT)); + // @see set_var::is_var_optimizer_trace() +export sys_var *Sys_optimizer_trace_ptr = &Sys_optimizer_trace; + +static Sys_var_ulong Sys_optimizer_trace_max_mem_size( + "optimizer_trace_max_mem_size", + "Maximum allowed size of an optimizer trace", + SESSION_VAR(optimizer_trace_max_mem_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, ULONG_MAX), DEFAULT(1024 * 1024), BLOCK_SIZE(1)); + static Sys_var_charptr Sys_pid_file( "pid_file", "Pid file used by safe_mysqld", READ_ONLY GLOBAL_VAR(pidfile_name_ptr), CMD_LINE(REQUIRED_ARG), diff --git a/sql/table.cc b/sql/table.cc index 375f7a3f65f..d5c88b226c7 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -44,6 +44,7 @@ #include "sql_cte.h" #include "ha_sequence.h" #include "sql_show.h" +#include "opt_trace.h" /* For MySQL 5.7 virtual fields */ #define MYSQL57_GENERATED_FIELD 128 @@ -5714,6 +5715,7 @@ bool TABLE_LIST::prepare_security(THD *thd) if (prepare_view_security_context(thd)) DBUG_RETURN(TRUE); thd->security_ctx= find_view_security_context(thd); + opt_trace_disable_if_no_security_context_access(thd); while ((tbl= tb++)) { DBUG_ASSERT(tbl->referencing_view); From 27c3abde3071ad2010cbcda5b07435ad15364a70 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 12 Feb 2019 22:56:24 -0800 Subject: [PATCH 72/91] MDEV-17096 Pushdown of simple derived tables to storage engines MDEV-17631 select_handler for a full query pushdown Added comments and file headers for files introduced in these tasks. --- sql/derived_handler.cc | 63 +++++++++++++++++++---- sql/derived_handler.h | 30 +++++++++-- sql/select_handler.cc | 43 ++++++++++++++++ sql/select_handler.h | 28 +++++++++- sql/sql_derived.cc | 21 ++++++++ sql/sql_lex.h | 2 + sql/sql_select.cc | 26 ++++++++++ sql/table.h | 6 +++ storage/federatedx/federatedx_pushdown.cc | 19 +++++++ 9 files changed, 223 insertions(+), 15 deletions(-) diff --git a/sql/derived_handler.cc b/sql/derived_handler.cc index 1fa5e94a1d4..76fd736de2b 100644 --- a/sql/derived_handler.cc +++ b/sql/derived_handler.cc @@ -1,18 +1,41 @@ +/* + Copyright (c) 2018, 2019 MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + #include "mariadb.h" #include "sql_priv.h" #include "sql_select.h" #include "derived_handler.h" -void derived_handler::set_derived(TABLE_LIST *tbl) -{ - derived= tbl; - table= tbl->table; - unit= tbl->derived; - select= unit->first_select(); - tmp_table_param= select->next_select() ? - ((select_unit *)(unit->result))->get_tmp_table_param() : - &select->join->tmp_table_param; -} + +/** + The methods of the Pushdown_derived class. + + The objects of this class are used for pushdown of the derived tables + into engines. The main method of the class is Pushdown_derived::execute() + that initiates execution of the query specifying a derived by a foreign + engine, receives the rows of the result set and put them in a temporary + table on the server side. + + The method uses only the functions of the derived_handle interface to do + this. The constructor of the class gets this interface as a parameter. + + Currently a derived tables pushed into an engine is always materialized. + It could be changed if the cases when the tables is used as driving table. +*/ + Pushdown_derived::Pushdown_derived(TABLE_LIST *tbl, derived_handler *h) : derived(tbl), handler(h) @@ -20,11 +43,13 @@ Pushdown_derived::Pushdown_derived(TABLE_LIST *tbl, derived_handler *h) is_analyze= handler->thd->lex->analyze_stmt; } + Pushdown_derived::~Pushdown_derived() { delete handler; } + int Pushdown_derived::execute() { int err; @@ -82,3 +107,21 @@ error_2: DBUG_RETURN(-1); // Error not sent to client } + +void derived_handler::print_error(int error, myf errflag) +{ + my_error(ER_GET_ERRNO, MYF(0), error, hton_name(ht)->str); +} + + +void derived_handler::set_derived(TABLE_LIST *tbl) +{ + derived= tbl; + table= tbl->table; + unit= tbl->derived; + select= unit->first_select(); + tmp_table_param= select->next_select() ? + ((select_unit *)(unit->result))->get_tmp_table_param() : + &select->join->tmp_table_param; +} + diff --git a/sql/derived_handler.h b/sql/derived_handler.h index c312a93a1f7..171165bbe6f 100644 --- a/sql/derived_handler.h +++ b/sql/derived_handler.h @@ -1,3 +1,19 @@ +/* + Copyright (c) 2016, 2017 MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + #ifndef DERIVED_HANDLER_INCLUDED #define DERIVED_HANDLER_INCLUDED @@ -8,6 +24,13 @@ class TMP_TABLE_PARAM; typedef class st_select_lex_unit SELECT_LEX_UNIT; +/** + @class derived_handler + + This interface class is to be used for execution of queries that specify + derived table by foreign engines +*/ + class derived_handler { public: @@ -23,11 +46,12 @@ public: */ TABLE *table; + /* The parameters if the temporary table used at its creation */ TMP_TABLE_PARAM *tmp_table_param; - SELECT_LEX_UNIT *unit; + SELECT_LEX_UNIT *unit; // Specifies the derived table - SELECT_LEX *select; + SELECT_LEX *select; // The first select of the specification derived_handler(THD *thd_arg, handlerton *ht_arg) : thd(thd_arg), ht(ht_arg), derived(0),table(0), tmp_table_param(0), @@ -53,7 +77,7 @@ public: virtual int end_scan()=0; /* Report errors */ - virtual void print_error(int error, myf errflag)=0; + virtual void print_error(int error, myf errflag); void set_derived(TABLE_LIST *tbl); }; diff --git a/sql/select_handler.cc b/sql/select_handler.cc index 9a8d3914b21..f020d2f6b80 100644 --- a/sql/select_handler.cc +++ b/sql/select_handler.cc @@ -1,21 +1,55 @@ +/* + Copyright (c) 2018, 2019 MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + #include "mariadb.h" #include "sql_priv.h" #include "sql_select.h" #include "select_handler.h" +/** + The methods of the Pushdown_select class. + + The objects of this class are used for pushdown of the select queries + into engines. The main method of the class is Pushdown_select::execute() + that initiates execution of a select query by a foreign engine, receives the + rows of the result set, put it in a buffer of a temporary table and send + them from the buffer directly into output. + + The method uses the functions of the select_handle interface to do this. + It also employes plus some helper functions to create the needed temporary + table and to send rows from the temporary table into output. + The constructor of the class gets the select_handler interface as a parameter. +*/ + + Pushdown_select::Pushdown_select(SELECT_LEX *sel, select_handler *h) : select(sel), handler(h) { is_analyze= handler->thd->lex->analyze_stmt; } + Pushdown_select::~Pushdown_select() { delete handler; select->select_h= NULL; } + bool Pushdown_select::init() { List types; @@ -38,6 +72,7 @@ bool Pushdown_select::init() DBUG_RETURN(false); } + bool Pushdown_select::send_result_set_metadata() { THD *thd= handler->thd; @@ -59,6 +94,7 @@ bool Pushdown_select::send_result_set_metadata() DBUG_RETURN(false); } + bool Pushdown_select::send_data() { THD *thd= handler->thd; @@ -83,6 +119,7 @@ bool Pushdown_select::send_data() DBUG_RETURN(false); } + bool Pushdown_select::send_eof() { THD *thd= handler->thd; @@ -98,6 +135,7 @@ bool Pushdown_select::send_eof() DBUG_RETURN(false); } + int Pushdown_select::execute() { int err; @@ -143,3 +181,8 @@ error_2: handler->print_error(err, MYF(0)); DBUG_RETURN(-1); // Error not sent to client } + +void select_handler::print_error(int error, myf errflag) +{ + my_error(ER_GET_ERRNO, MYF(0), error, hton_name(ht)->str); +} diff --git a/sql/select_handler.h b/sql/select_handler.h index 19a1883f6c7..e2ad13b7cdf 100644 --- a/sql/select_handler.h +++ b/sql/select_handler.h @@ -1,20 +1,44 @@ +/* + Copyright (c) 2018, 2019 MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + #ifndef SELECT_HANDLER_INCLUDED #define SELECT_HANDLER_INCLUDED #include "mariadb.h" #include "sql_priv.h" +/** + @class select_handler + + This interface class is to be used for execution of select queries + by foreign engines +*/ + class select_handler { public: THD *thd; handlerton *ht; - SELECT_LEX *select; + SELECT_LEX *select; // Select to be excuted /* Temporary table where all results should be stored in record[0] The table has a field for every item from the select_lex::item_list. + The table is actually never filled. Only its record buffer is used. */ TABLE *table; @@ -42,7 +66,7 @@ class select_handler virtual int end_scan() = 0; /* Report errors */ - virtual void print_error(int error, myf errflag) = 0; + virtual void print_error(int error, myf errflag); }; #endif /* SELECT_HANDLER_INCLUDED */ diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 564049e59e1..fbd8365e619 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -932,6 +932,7 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) if (derived->is_materialized_derived() && derived->dt_handler) { + /* Create an object for execution of the query specifying the table */ if (!(derived->pushdown_derived= new (thd->mem_root) Pushdown_derived(derived, derived->dt_handler))) { @@ -1151,6 +1152,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) int res; if (unit->executed) DBUG_RETURN(FALSE); + /* Execute the query that specifies the derived table by a foreign engine */ res= derived->pushdown_derived->execute(); unit->executed= true; delete derived->pushdown_derived; @@ -1457,6 +1459,25 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) } +/** + @brief + Look for provision of the derived_handler interface by a foreign engine + + @param thd The thread handler + + @details + The function looks through its tables of the query that specifies this + derived table searching for a table whose handlerton owns a + create_derived call-back function. If the call of this function returns + a derived_handler interface object then the server will push the query + specifying the derived table into this engine. + This is a responsibility of the create_derived call-back function to + check whether the engine can execute the query. + + @retval the found derived_handler if the search is successful + 0 otherwise +*/ + derived_handler *TABLE_LIST::find_derived_handler(THD *thd) { if (!derived || is_recursive_with_table()) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index c33307c523b..25e8ad3c727 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1257,7 +1257,9 @@ public: table_value_constr *tvc; bool in_tvc; + /* The interface employed to execute the select query by a foreign engine */ select_handler *select_h; + /* The object used to organize execution of the query by a foreign engine */ Pushdown_select *pushdown_select; /** System Versioning */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e9040e197e0..38b0e7eb6e7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1444,7 +1444,10 @@ int JOIN::optimize() if (select_lex->pushdown_select) { if (!(select_options & SELECT_DESCRIBE)) + { + /* Prepare to execute the query pushed into a foreign engine */ res= select_lex->pushdown_select->init(); + } with_two_phase_optimization= false; } else if (optimization_state == JOIN::OPTIMIZATION_PHASE_1_DONE) @@ -4074,6 +4077,7 @@ void JOIN::exec_inner() } else if (select_lex->pushdown_select) { + /* Execute the query pushed into a foreign engine */ error= select_lex->pushdown_select->execute(); DBUG_VOID_RETURN; } @@ -4288,9 +4292,11 @@ mysql_select(THD *thd, } } + /* Look for a table owned by an engine with the select_handler interface */ select_lex->select_h= select_lex->find_select_handler(thd); if (select_lex->select_h) { + /* Create a Pushdown_select object for later execution of the query */ if (!(select_lex->pushdown_select= new (thd->mem_root) Pushdown_select(select_lex, select_lex->select_h))) @@ -27620,6 +27626,26 @@ Item *remove_pushed_top_conjuncts(THD *thd, Item *cond) return cond; } + +/** + @brief + Look for provision of the select_handler interface by a foreign engine + + @param thd The thread handler + + @details + The function checks that this is an upper level select and if so looks + through its tables searching for one whose handlerton owns a + create_select call-back function. If the call of this function returns + a select_handler interface object then the server will push the select + query into this engine. + This is a responsibility of the create_select call-back function to + check whether the engine can execute the query. + + @retval the found select_handler if the search is successful + 0 otherwise +*/ + select_handler *SELECT_LEX::find_select_handler(THD *thd) { if (next_select()) diff --git a/sql/table.h b/sql/table.h index f7bcdaa58b2..40dd752deeb 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2136,8 +2136,14 @@ struct TABLE_LIST TABLE_LIST * next_with_rec_ref; bool is_derived_with_recursive_reference; bool block_handle_derived; + /* The interface employed to materialize the table by a foreign engine */ derived_handler *dt_handler; + /* The text of the query specifying the derived table */ LEX_CSTRING derived_spec; + /* + The object used to organize execution of the query that specifies + the derived table by a foreign engine + */ Pushdown_derived *pushdown_derived; ST_SCHEMA_TABLE *schema_table; /* Information_schema table */ st_select_lex *schema_select_lex; diff --git a/storage/federatedx/federatedx_pushdown.cc b/storage/federatedx/federatedx_pushdown.cc index 906d87c29ce..2bcee943308 100644 --- a/storage/federatedx/federatedx_pushdown.cc +++ b/storage/federatedx/federatedx_pushdown.cc @@ -16,6 +16,25 @@ /* !!! For inclusion into ha_federatedx.cc */ + +/* + This is a quick a dirty implemention of the derived_handler and select_handler + interfaces to be used to push select queries and the queries specifying + derived tables into FEDERATEDX engine. + The functions + create_federatedx_derived_handler and + create_federatedx_select_handler + that return the corresponding interfaces for pushdown capabilities do + not check a lot of things. In particular they do not check that the tables + of the pushed queries belong to the same foreign server. + + The implementation is provided purely for testing purposes. + The pushdown capabilities are enabled by turning on the plugin system + variable federated_pushdown: + set global federated_pushdown=1; +*/ + + static derived_handler* create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived) { From d28dab7658773078d5d57df985209027f3ab2bbb Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 13 Feb 2019 12:15:14 +0100 Subject: [PATCH 73/91] Fix compilation on old gcc --- sql/my_json_writer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/my_json_writer.h b/sql/my_json_writer.h index 4701cb4165b..3234c748f5d 100644 --- a/sql/my_json_writer.h +++ b/sql/my_json_writer.h @@ -111,7 +111,7 @@ class String_with_limit { public: - String_with_limit() : size_limit(SIZE_MAX), truncated_len(0) + String_with_limit() : size_limit(SIZE_T_MAX), truncated_len(0) { str.length(0); } From 6476126cbaa37990ea42d1bacf6faee12eaff1f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Wed, 13 Feb 2019 08:39:44 +0200 Subject: [PATCH 74/91] MDEV-18564: Change wsrep_load_data_splitting off by default Variable wsrep_load_data_splitting is deprecated and should be off by default. --- mysql-test/suite/galera/r/galera_defaults.result | 2 +- .../suite/galera/r/galera_var_load_data_splitting.result | 6 +++++- mysql-test/suite/galera/r/partition.result | 2 +- .../suite/galera/t/galera_var_load_data_splitting.test | 3 +++ mysql-test/suite/sys_vars/r/sysvars_wsrep.result | 4 ++-- .../suite/sys_vars/r/wsrep_load_data_splitting_basic.result | 4 ++-- sql/sys_vars.cc | 2 +- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result index 20ea590e2e5..4aef4f5e48c 100644 --- a/mysql-test/suite/galera/r/galera_defaults.result +++ b/mysql-test/suite/galera/r/galera_defaults.result @@ -34,7 +34,7 @@ WSREP_FORCED_BINLOG_FORMAT NONE WSREP_GTID_DOMAIN_ID 0 WSREP_GTID_MODE OFF WSREP_IGNORE_APPLY_ERRORS 7 -WSREP_LOAD_DATA_SPLITTING ON +WSREP_LOAD_DATA_SPLITTING OFF WSREP_LOG_CONFLICTS OFF WSREP_MAX_WS_ROWS 0 WSREP_MAX_WS_SIZE 2147483647 diff --git a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result index 9078e9ea985..66bc6bc4a9a 100644 --- a/mysql-test/suite/galera/r/galera_var_load_data_splitting.result +++ b/mysql-test/suite/galera/r/galera_var_load_data_splitting.result @@ -12,7 +12,11 @@ COUNT(*) = 95000 wsrep_last_committed_diff 1 connection node_1; -SET GLOBAL wsrep_load_data_splitting = 1;; +SET GLOBAL wsrep_load_data_splitting = 0;; +Warnings: +Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release +connection node_2; +SET GLOBAL wsrep_load_data_splitting = 0;; Warnings: Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release DROP TABLE t1; diff --git a/mysql-test/suite/galera/r/partition.result b/mysql-test/suite/galera/r/partition.result index 213f9dfdbab..2e16d06519c 100644 --- a/mysql-test/suite/galera/r/partition.result +++ b/mysql-test/suite/galera/r/partition.result @@ -159,7 +159,7 @@ wsrep_last_committed_diff AS_EXPECTED_1_or_2 DROP TABLE t1; connection node_1; -SET GLOBAL wsrep_load_data_splitting = 1;; +SET GLOBAL wsrep_load_data_splitting = 0;; Warnings: Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release disconnect node_2; diff --git a/mysql-test/suite/galera/t/galera_var_load_data_splitting.test b/mysql-test/suite/galera/t/galera_var_load_data_splitting.test index 38dab0a981b..621cb69fc16 100644 --- a/mysql-test/suite/galera/t/galera_var_load_data_splitting.test +++ b/mysql-test/suite/galera/t/galera_var_load_data_splitting.test @@ -36,4 +36,7 @@ SELECT COUNT(*) = 95000 FROM t1; --connection node_1 --eval SET GLOBAL wsrep_load_data_splitting = $wsrep_load_data_splitting_orig; +--connection node_2 +--eval SET GLOBAL wsrep_load_data_splitting = $wsrep_load_data_splitting_orig; + DROP TABLE t1; diff --git a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result index dd3e70c587d..49eaaa965dc 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result +++ b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result @@ -227,9 +227,9 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME WSREP_LOAD_DATA_SPLITTING SESSION_VALUE NULL -GLOBAL_VALUE ON +GLOBAL_VALUE OFF GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE ON +DEFAULT_VALUE OFF VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN VARIABLE_COMMENT To commit LOAD DATA transaction after every 10K rows inserted (deprecated) diff --git a/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result b/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result index d373a3832d5..3171a690486 100644 --- a/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result +++ b/mysql-test/suite/sys_vars/r/wsrep_load_data_splitting_basic.result @@ -6,7 +6,7 @@ SET @wsrep_load_data_splitting_global_saved = @@global.wsrep_load_data_splitting # default SELECT @@global.wsrep_load_data_splitting; @@global.wsrep_load_data_splitting -1 +0 # scope SELECT @@session.wsrep_load_data_splitting; @@ -42,7 +42,7 @@ Warnings: Warning 1287 '@@wsrep_load_data_splitting' is deprecated and will be removed in a future release SELECT @@global.wsrep_load_data_splitting; @@global.wsrep_load_data_splitting -1 +0 # invalid values SET @@global.wsrep_load_data_splitting=NULL; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index a8b557c90c8..ad576280d3d 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5540,7 +5540,7 @@ static Sys_var_mybool Sys_wsrep_load_data_splitting( "wsrep_load_data_splitting", "To commit LOAD DATA " "transaction after every 10K rows inserted (deprecated)", GLOBAL_VAR(wsrep_load_data_splitting), - CMD_LINE(OPT_ARG), DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, + CMD_LINE(OPT_ARG), DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0), DEPRECATED("")); static Sys_var_mybool Sys_wsrep_slave_FK_checks( From 8ef4105a890390440a487a2d8ddabef5149018df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Feb 2019 15:46:04 +0200 Subject: [PATCH 75/91] MDEV-6111: Adjust a result --- mysql-test/main/information_schema-big.result | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/main/information_schema-big.result b/mysql-test/main/information_schema-big.result index d4aa6deb2e2..b135621acb7 100644 --- a/mysql-test/main/information_schema-big.result +++ b/mysql-test/main/information_schema-big.result @@ -36,6 +36,7 @@ GLOBAL_VARIABLES VARIABLE_NAME INDEX_STATISTICS TABLE_SCHEMA KEY_CACHES KEY_CACHE_NAME KEY_COLUMN_USAGE CONSTRAINT_SCHEMA +OPTIMIZER_TRACE QUERY PARAMETERS SPECIFIC_SCHEMA PARTITIONS TABLE_SCHEMA PLUGINS PLUGIN_NAME @@ -94,6 +95,7 @@ GLOBAL_VARIABLES VARIABLE_NAME INDEX_STATISTICS TABLE_SCHEMA KEY_CACHES KEY_CACHE_NAME KEY_COLUMN_USAGE CONSTRAINT_SCHEMA +OPTIMIZER_TRACE QUERY PARAMETERS SPECIFIC_SCHEMA PARTITIONS TABLE_SCHEMA PLUGINS PLUGIN_NAME From ad17875c0d39453395f33e8c2a39cc4b2601df2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Feb 2019 15:46:52 +0200 Subject: [PATCH 76/91] MDEV-15563: Allow instant VARCHAR extension from <128 bytes For up to 127 bytes length, InnoDB would use 1 byte for length, and that byte would always be less than 128. If the maximum length is longer than 255 bytes, InnoDB would use a variable-length encoding for the length, using 1 byte for lengths up to 127 bytes, and 2 bytes for longer lengths. Thus, 1-byte lengths are always compatible when the maximum size changes from less than 128 bytes to anything longer. Field_varstring::is_equal(): Return IS_EQUAL_PACK_LENGTH also when converting from VARCHAR less than 128 bytes to any longer VARCHAR. --- .../suite/innodb/r/alter_varchar_change.result | 17 +++++++++++++++++ .../suite/innodb/t/alter_varchar_change.test | 12 ++++++++++++ sql/field.cc | 12 ++++++++---- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/r/alter_varchar_change.result b/mysql-test/suite/innodb/r/alter_varchar_change.result index 25adde6ffe4..2425c8382e0 100644 --- a/mysql-test/suite/innodb/r/alter_varchar_change.result +++ b/mysql-test/suite/innodb/r/alter_varchar_change.result @@ -412,6 +412,23 @@ ALTER TABLE t1 MODIFY f2 VARCHAR(300); CALL get_table_id("test/t1", @tbl1_id); SELECT @tbl1_id = @tbl_id; @tbl1_id = @tbl_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(300) DEFAULT NULL, + KEY `idx` (`f2`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(128), +INDEX idx(f2(40)))ENGINE=InnoDB; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(300); +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id 0 SHOW CREATE TABLE t1; Table Create Table diff --git a/mysql-test/suite/innodb/t/alter_varchar_change.test b/mysql-test/suite/innodb/t/alter_varchar_change.test index 7e0c99487b5..7fc770139ad 100644 --- a/mysql-test/suite/innodb/t/alter_varchar_change.test +++ b/mysql-test/suite/innodb/t/alter_varchar_change.test @@ -306,6 +306,18 @@ SELECT @tbl1_id = @tbl_id; SHOW CREATE TABLE t1; DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(128), + INDEX idx(f2(40)))ENGINE=InnoDB; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(300); +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), INDEX idx(f2(40)))ENGINE=InnoDB; diff --git a/sql/field.cc b/sql/field.cc index dd125a06bad..85d8ccb069d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7901,17 +7901,21 @@ Field *Field_varstring::new_key_field(MEM_ROOT *root, TABLE *new_table, uint Field_varstring::is_equal(Create_field *new_field) { + if (new_field->length < field_length) + return IS_EQUAL_NO; + if (new_field->type_handler() == type_handler() && new_field->charset == field_charset && !new_field->compression_method() == !compression_method()) { if (new_field->length == field_length) return IS_EQUAL_YES; - if (new_field->length > field_length && - ((new_field->length <= 255 && field_length <= 255) || - (new_field->length > 255 && field_length > 255))) - return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer variable length + if (field_length <= 127 || + new_field->length <= 255 || + field_length > 255) + return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length } + return IS_EQUAL_NO; } From 0ae3ea7919da05b9eecd2160bbe5726be163d4ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Feb 2019 16:42:03 +0200 Subject: [PATCH 77/91] MDEV-15563: Instant VARCHAR extension for ROW_FORMAT=REDUNDANT In the original InnoDB storage format (which was retroactively named ROW_FORMAT=REDUNDANT in MySQL 5.0.3), the length of each index field is stored explicitly. Thus, we can and from now on will allow arbitrary extension of VARBINARY and VARCHAR columns when the table is in ROW_FORMAT=REDUNDANT. ha_innobase::open(): Advertise a new HA_EXTENDED_TYPES_CONVERSION capability for ROW_FORMAT=REDUNDANT tables. Field_varstring::is_equal(): If the HA_EXTENDED_TYPES_CONVERSION capability is advertised for the table, return IS_EQUAL_PACK_LENGTH for any length extension. --- .../suite/innodb/r/alter_varchar_change.result | 17 +++++++++++++++++ .../suite/innodb/t/alter_varchar_change.test | 12 ++++++++++++ sql/field.cc | 5 +++-- sql/handler.h | 13 +++++++++++-- storage/innobase/handler/ha_innodb.cc | 5 +++++ 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/innodb/r/alter_varchar_change.result b/mysql-test/suite/innodb/r/alter_varchar_change.result index 2425c8382e0..ce729fe5612 100644 --- a/mysql-test/suite/innodb/r/alter_varchar_change.result +++ b/mysql-test/suite/innodb/r/alter_varchar_change.result @@ -439,6 +439,23 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t1; CREATE TABLE t1(f1 INT NOT NULL, +f2 VARCHAR(128), +INDEX idx(f2(40)))ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(300); +CALL get_table_id("test/t1", @tbl1_id); +SELECT @tbl1_id = @tbl_id; +@tbl1_id = @tbl_id +1 +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` varchar(300) DEFAULT NULL, + KEY `idx` (`f2`(40)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), INDEX idx(f2(40)))ENGINE=InnoDB; CALL get_table_id("test/t1", @tbl_id); diff --git a/mysql-test/suite/innodb/t/alter_varchar_change.test b/mysql-test/suite/innodb/t/alter_varchar_change.test index 7fc770139ad..9769c63ac5e 100644 --- a/mysql-test/suite/innodb/t/alter_varchar_change.test +++ b/mysql-test/suite/innodb/t/alter_varchar_change.test @@ -318,6 +318,18 @@ SELECT @tbl1_id = @tbl_id; SHOW CREATE TABLE t1; DROP TABLE t1; +CREATE TABLE t1(f1 INT NOT NULL, + f2 VARCHAR(128), + INDEX idx(f2(40)))ENGINE=InnoDB ROW_FORMAT=REDUNDANT; + +CALL get_table_id("test/t1", @tbl_id); +ALTER TABLE t1 MODIFY f2 VARCHAR(300); +CALL get_table_id("test/t1", @tbl1_id); + +SELECT @tbl1_id = @tbl_id; +SHOW CREATE TABLE t1; +DROP TABLE t1; + CREATE TABLE t1(f1 INT NOT NULL, f2 VARCHAR(100), INDEX idx(f2(40)))ENGINE=InnoDB; diff --git a/sql/field.cc b/sql/field.cc index 85d8ccb069d..a19ff0a06d9 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2008, 2017, MariaDB + Copyright (c) 2008, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -7912,7 +7912,8 @@ uint Field_varstring::is_equal(Create_field *new_field) return IS_EQUAL_YES; if (field_length <= 127 || new_field->length <= 255 || - field_length > 255) + field_length > 255 || + (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)) return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length } diff --git a/sql/handler.h b/sql/handler.h index afe62123170..be3aefb98d2 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2,7 +2,7 @@ #define HANDLER_INCLUDED /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2009, 2018, MariaDB + Copyright (c) 2009, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -319,6 +319,11 @@ enum enum_alter_inplace_result { /* Safe for online backup */ #define HA_CAN_ONLINE_BACKUPS (1ULL << 56) +/** whether every data field explicitly stores length +(holds for InnoDB ROW_FORMAT=REDUNDANT) */ +#define HA_EXTENDED_TYPES_CONVERSION (1ULL << 57) +#define HA_LAST_TABLE_FLAG HA_EXTENDED_TYPES_CONVERSION + /* bits in index_flags(index_number) for what you can do with index */ #define HA_READ_NEXT 1 /* TODO really use this flag */ #define HA_READ_PREV 2 /* supports ::index_prev */ @@ -3141,7 +3146,11 @@ public: /** The cached_table_flags is set at ha_open and ha_external_lock */ - Table_flags ha_table_flags() const { return cached_table_flags; } + Table_flags ha_table_flags() const + { + DBUG_ASSERT(cached_table_flags < (HA_LAST_TABLE_FLAG << 1)); + return cached_table_flags; + } /** These functions represent the public interface to *users* of the handler class, hence they are *not* virtual. For the inheritance diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ee986d55f77..50d0ad42094 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6121,6 +6121,11 @@ no_such_table: DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); } + if (!ib_table->not_redundant()) { + m_int_table_flags |= HA_EXTENDED_TYPES_CONVERSION; + cached_table_flags |= HA_EXTENDED_TYPES_CONVERSION; + } + size_t n_fields = omits_virtual_cols(*table_share) ? table_share->stored_fields : table_share->fields; size_t n_cols = dict_table_get_n_user_cols(ib_table) From 22feb179ae166500ec91feec6246c8154e33f9a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Feb 2019 17:39:05 +0200 Subject: [PATCH 78/91] MDEV-15563: Instant ROW_FORMAT=REDUNDANT column extension This was developed by Aleksey Midenkov based on my design. In the original InnoDB storage format (that was retroactively named ROW_FORMAT=REDUNDANT in MySQL 5.0.3), the length of each index field is stored explicitly. Because of this, we can and now will allow instant conversion from VARCHAR to CHAR or VARBINARY to BINARY of equal or greater size, as well as instant conversion of TINYINT to SMALLINT to MEDIUMINT to INT to BIGINT (while not changing between signed and unsigned). Theoretically, we could allow changing from an unsigned integer to a bigger unsigned integer, as well as changing CHAR to VARCHAR, but that would require additional metadata and conversions whenever reading old records. Field_str::is_equal(), Field_varstring::is_equal(), Field_num::is_equal(): Return the new result IS_EQUAL_PACK_LENGTH_EXT if the table advertises HA_EXTENDED_TYPES_CONVERSION capability and we are considering the above-mentioned conversions. ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT: A new ALTER TABLE flag, similar to ALTER_COLUMN_EQUAL_PACK_LENGTH but requiring conversions when reading the data. The Field::is_equal() result IS_EQUAL_PACK_LENGTH_EXT will map to this flag. dtype_get_fixed_size_low(): For BINARY, CHAR and integer columns in ROW_FORMAT=REDUNDANT, return 0 (variable length) from now on. dtype_get_sql_null_size(): Keep returning the current size for BINARY, CHAR and integer columns, so that in ROW_FORMAT=REDUNDANT it will remain possible to update in place between NULL and NOT NULL values. btr_index_rec_validate(): Relax a CHECK TABLE length check for ROW_FORMAT=REDUNDANT tables. btr_cur_instant_init_low(): No longer trust fixed_len for ROW_FORMAT=REDUNDANT tables. We cannot rely on fixed_len anymore because the record can have shorter length from before instant extension. Note that importing such tablespace into earlier MariaDB versions produces ER_TABLE_SCHEMA_MISMATCH when using a .cfg file. --- .../innodb/r/instant_alter_extend,utf8.rdiff | 29 +++ .../innodb/r/instant_alter_extend.result | 235 ++++++++++++++++++ .../t/instant_alter_extend.combinations | 5 + .../suite/innodb/t/instant_alter_extend.test | 226 +++++++++++++++++ sql/field.cc | 62 +++-- sql/field.h | 2 +- sql/handler.h | 8 + sql/sql_priv.h | 14 +- sql/sql_table.cc | 3 + storage/innobase/btr/btr0btr.cc | 4 +- storage/innobase/btr/btr0cur.cc | 10 +- storage/innobase/dict/dict0dict.cc | 8 + storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/handler/handler0alter.cc | 57 +++-- storage/innobase/include/data0type.ic | 22 +- storage/innobase/include/dict0mem.h | 53 +++- storage/innobase/row/row0merge.cc | 5 - storage/innobase/row/row0mysql.cc | 13 +- storage/innobase/row/row0sel.cc | 10 +- 19 files changed, 697 insertions(+), 71 deletions(-) create mode 100644 mysql-test/suite/innodb/r/instant_alter_extend,utf8.rdiff create mode 100644 mysql-test/suite/innodb/r/instant_alter_extend.result create mode 100644 mysql-test/suite/innodb/t/instant_alter_extend.combinations create mode 100644 mysql-test/suite/innodb/t/instant_alter_extend.test diff --git a/mysql-test/suite/innodb/r/instant_alter_extend,utf8.rdiff b/mysql-test/suite/innodb/r/instant_alter_extend,utf8.rdiff new file mode 100644 index 00000000000..9b7196ccf9a --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_extend,utf8.rdiff @@ -0,0 +1,29 @@ +--- instant_alter_convert.result ++++ instant_alter_convert,utf8.result +@@ -37,7 +37,7 @@ + test.t check status OK + call check_table('t'); + name mtype prtype len +-a 2 800FE 200 ++a 13 2100FE 600 + # CHAR enlargement + alter table t modify a char(220), algorithm=instant; + select count(a) from t where a = @bigval; +@@ -51,7 +51,7 @@ + test.t check status OK + call check_table('t'); + name mtype prtype len +-a 2 800FE 200 ++a 13 2100FE 600 + # Convert from VARCHAR to a bigger CHAR + alter table t modify a varchar(200), algorithm=instant; + ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +@@ -72,7 +72,7 @@ + test.t check status OK + call check_table('t'); + name mtype prtype len +-a 2 800FE 255 ++a 13 2100FE 765 + # BINARY/VARBINARY test + create or replace table t (a varbinary(300)); + alter table t modify a binary(255), algorithm=instant; diff --git a/mysql-test/suite/innodb/r/instant_alter_extend.result b/mysql-test/suite/innodb/r/instant_alter_extend.result new file mode 100644 index 00000000000..1798f47104a --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_extend.result @@ -0,0 +1,235 @@ +# +# MDEV-15563: Instant ROW_FORMAT=REDUNDANT column type change&extension +# +create or replace database test; +use test; +set default_storage_engine=innodb; +set @save_format= @@GLOBAL.innodb_default_row_format; +SET GLOBAL innodb_default_row_format=redundant; +set @bigval= repeat('0123456789', 30); +create or replace procedure check_table(table_name varchar(255)) +begin +select table_id into @table_id +from information_schema.innodb_sys_tables +where name = concat('test/', table_name); +select name, mtype, hex(prtype) as prtype, len +from information_schema.innodb_sys_columns +where table_id = @table_id; +end~~ +# VARCHAR -> CHAR, VARBINARY -> BINARY conversion +set @bigval= repeat('0123456789', 20); +create or replace table t (a varchar(300)); +alter table t modify a char(255), algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table t modify a char(255), algorithm=copy; +create or replace table t (a varchar(200)); +insert into t values (@bigval); +insert into t values ('z'); +alter table t modify a char(200), algorithm=instant; +select count(a) from t where a = @bigval; +count(a) +1 +select a, length(a) from t where a = 'z'; +a length(a) +z 1 +check table t extended; +Table Op Msg_type Msg_text +test.t check status OK +call check_table('t'); +name mtype prtype len +a 2 800FE 200 +# CHAR enlargement +alter table t modify a char(220), algorithm=instant; +select count(a) from t where a = @bigval; +count(a) +1 +select a, length(a) from t where a = 'z'; +a length(a) +z 1 +check table t extended; +Table Op Msg_type Msg_text +test.t check status OK +call check_table('t'); +name mtype prtype len +a 2 800FE 200 +# Convert from VARCHAR to a bigger CHAR +alter table t modify a varchar(200), algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table t modify a varchar(200), algorithm=copy; +alter table t modify a char(255), algorithm=instant; +select count(a) from t where a = @bigval; +count(a) +1 +select a, length(a) from t where a = 'z'; +a length(a) +z 1 +select * from t; +a +01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +z +check table t extended; +Table Op Msg_type Msg_text +test.t check status OK +call check_table('t'); +name mtype prtype len +a 2 800FE 255 +# BINARY/VARBINARY test +create or replace table t (a varbinary(300)); +alter table t modify a binary(255), algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table t modify a binary(255), algorithm=copy; +create or replace table t (a varbinary(200)); +insert into t values (@bigval); +insert into t values ('z'); +alter table t modify a binary(200), algorithm=instant; +select count(a) from t where a = @bigval; +count(a) +1 +select length(a) from t where left(a, 1) = 'z'; +length(a) +200 +check table t extended; +Table Op Msg_type Msg_text +test.t check status OK +call check_table('t'); +name mtype prtype len +a 3 3F04FE 200 +# BINARY enlargement +alter table t modify a binary(220), algorithm=instant; +check table t extended; +Table Op Msg_type Msg_text +test.t check status OK +call check_table('t'); +name mtype prtype len +a 3 3F04FE 200 +# Convert from VARBINARY to a bigger BINARY +alter table t modify a varbinary(220), algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table t modify a varbinary(220), algorithm=copy; +alter table t modify a binary(255), algorithm=instant; +select count(a) from t where a = @bigval; +count(a) +0 +select a, length(a) from t where a = 'z'; +a length(a) +select * from t; +a +01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +z +check table t extended; +Table Op Msg_type Msg_text +test.t check status OK +call check_table('t'); +name mtype prtype len +a 3 3F04FE 255 +# Integer conversions +create or replace table t (x tinyint); +insert into t values (127); +alter table t modify x smallint, algorithm=instant; +select * from t; +x +127 +check table t extended; +Table Op Msg_type Msg_text +test.t check status OK +call check_table('t'); +name mtype prtype len +x 6 402 2 +update t set x= 32767; +alter table t modify x mediumint, algorithm=instant; +select * from t; +x +32767 +check table t extended; +Table Op Msg_type Msg_text +test.t check status OK +call check_table('t'); +name mtype prtype len +x 6 409 3 +update t set x= 8388607; +alter table t modify x int, algorithm=instant; +select * from t; +x +8388607 +check table t extended; +Table Op Msg_type Msg_text +test.t check status OK +call check_table('t'); +name mtype prtype len +x 6 403 4 +update t set x= 2147483647; +alter table t modify x bigint, algorithm=instant; +select * from t; +x +2147483647 +check table t extended; +Table Op Msg_type Msg_text +test.t check status OK +call check_table('t'); +name mtype prtype len +x 6 408 8 +# Check IMPORT TABLESPACE +create or replace table t2 (x int); +alter table t2 discard tablespace; +create or replace table t1 (x tinyint); +insert into t1 set x= 42; +alter table t1 modify x int; +flush tables t1 for export; +unlock tables; +alter table t2 import tablespace; +select * from t2; +x +42 +check table t2 extended; +Table Op Msg_type Msg_text +test.t2 check status OK +call check_table('t2'); +name mtype prtype len +x 6 403 4 +# Check innobase_col_to_mysql() len < flen +create or replace table t1 (x mediumint); +insert into t1 values (1); +insert into t1 values (1); +alter table t1 add column y int first, modify x int, algorithm instant; +alter table t1 add column z int first, add primary key (x); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +# Check assertion in wrong instant operation +create or replace table t1 (a varchar(26) not null) default character set utf8mb4; +alter table t1 modify a varchar(25) not null; +# Check row_mysql_store_col_in_innobase_format() +create or replace table t1(x int primary key, a varchar(20)); +insert into t1 (x) values (1); +update t1 set a= 'foo' where x = 2; +# +# MDEV-18124 PK on inplace-enlarged type fails +# +create or replace table t1 (x int, y int); +insert into t1 (x, y) values (11, 22); +alter table t1 modify x bigint, algorithm instant; +alter table t1 add primary key (x), algorithm inplace; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +create or replace table t1 (a varchar(10), y int); +insert into t1 (a, y) values ("0123456789", 33); +alter table t1 modify a char(15), algorithm instant; +alter table t1 add primary key (a), algorithm inplace; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +create or replace table t1 (x int primary key, y int); +insert into t1 (x, y) values (44, 55); +alter table t1 modify x bigint, algorithm inplace; +check table t1; +Table Op Msg_type Msg_text +test.t1 check status OK +create or replace table t1 (x int primary key, y int); +insert into t1 values (66, 77); +alter table t1 add column z int, algorithm instant; +alter table t1 drop column y, algorithm instant; +create or replace table t1 (x integer, a varchar(20)); +alter table t1 add index idx3 (a); +insert into t1 (x, a) values (73, 'a'); +alter table t1 modify a char(20); +create or replace database test charset latin1; +SET GLOBAL innodb_default_row_format=@save_format; diff --git a/mysql-test/suite/innodb/t/instant_alter_extend.combinations b/mysql-test/suite/innodb/t/instant_alter_extend.combinations new file mode 100644 index 00000000000..1465bf59ad7 --- /dev/null +++ b/mysql-test/suite/innodb/t/instant_alter_extend.combinations @@ -0,0 +1,5 @@ +[latin1] +character-set-server=latin1 + +[utf8] +character-set-server=utf8 diff --git a/mysql-test/suite/innodb/t/instant_alter_extend.test b/mysql-test/suite/innodb/t/instant_alter_extend.test new file mode 100644 index 00000000000..4ffa39c4f13 --- /dev/null +++ b/mysql-test/suite/innodb/t/instant_alter_extend.test @@ -0,0 +1,226 @@ +--source include/have_innodb.inc +--source include/maybe_debug.inc + +-- echo # +-- echo # MDEV-15563: Instant ROW_FORMAT=REDUNDANT column type change&extension +-- echo # + +# Use character-set-server in test db +create or replace database test; +use test; + +set default_storage_engine=innodb; +set @save_format= @@GLOBAL.innodb_default_row_format; +SET GLOBAL innodb_default_row_format=redundant; +set @bigval= repeat('0123456789', 30); + +delimiter ~~; +create or replace procedure check_table(table_name varchar(255)) +begin + select table_id into @table_id + from information_schema.innodb_sys_tables + where name = concat('test/', table_name); + select name, mtype, hex(prtype) as prtype, len + from information_schema.innodb_sys_columns + where table_id = @table_id; +end~~ +delimiter ;~~ + + +--echo # VARCHAR -> CHAR, VARBINARY -> BINARY conversion +set @bigval= repeat('0123456789', 20); + +create or replace table t (a varchar(300)); +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table t modify a char(255), algorithm=instant; +alter table t modify a char(255), algorithm=copy; + +create or replace table t (a varchar(200)); +if ($have_debug) { +--disable_query_log +--disable_result_log +set debug_dbug= '+d,ib_instant_error'; +--error ER_RECORD_FILE_FULL +alter table t modify a char(200); +set debug_dbug= default; +--enable_query_log +--enable_result_log +} +insert into t values (@bigval); +insert into t values ('z'); +alter table t modify a char(200), algorithm=instant; +select count(a) from t where a = @bigval; +select a, length(a) from t where a = 'z'; + +check table t extended; +call check_table('t'); + +--echo # CHAR enlargement +alter table t modify a char(220), algorithm=instant; +select count(a) from t where a = @bigval; +select a, length(a) from t where a = 'z'; + +check table t extended; +call check_table('t'); + +--echo # Convert from VARCHAR to a bigger CHAR +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table t modify a varchar(200), algorithm=instant; +alter table t modify a varchar(200), algorithm=copy; +alter table t modify a char(255), algorithm=instant; +select count(a) from t where a = @bigval; +select a, length(a) from t where a = 'z'; + +select * from t; +check table t extended; +call check_table('t'); + +--echo # BINARY/VARBINARY test +create or replace table t (a varbinary(300)); +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table t modify a binary(255), algorithm=instant; +alter table t modify a binary(255), algorithm=copy; + +create or replace table t (a varbinary(200)); +if ($have_debug) { +--disable_query_log +--disable_result_log +set debug_dbug= '+d,ib_instant_error'; +--error ER_RECORD_FILE_FULL +alter table t modify a binary(200); +set debug_dbug= default; +--enable_query_log +--enable_result_log +} +insert into t values (@bigval); +insert into t values ('z'); +alter table t modify a binary(200), algorithm=instant; +select count(a) from t where a = @bigval; +select length(a) from t where left(a, 1) = 'z'; + +check table t extended; +call check_table('t'); + +--echo # BINARY enlargement +alter table t modify a binary(220), algorithm=instant; + +check table t extended; +call check_table('t'); + +--echo # Convert from VARBINARY to a bigger BINARY +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table t modify a varbinary(220), algorithm=instant; +alter table t modify a varbinary(220), algorithm=copy; +alter table t modify a binary(255), algorithm=instant; +select count(a) from t where a = @bigval; +select a, length(a) from t where a = 'z'; + +select * from t; +check table t extended; +call check_table('t'); + + +--echo # Integer conversions +create or replace table t (x tinyint); +if ($have_debug) { +--disable_query_log +--disable_result_log +set debug_dbug= '+d,ib_instant_error'; +--error ER_RECORD_FILE_FULL +alter table t modify x smallint; +set debug_dbug= default; +--enable_query_log +--enable_result_log +} +insert into t values (127); +alter table t modify x smallint, algorithm=instant; +select * from t; +check table t extended; +call check_table('t'); + +update t set x= 32767; +alter table t modify x mediumint, algorithm=instant; +select * from t; +check table t extended; +call check_table('t'); + +update t set x= 8388607; +alter table t modify x int, algorithm=instant; +select * from t; +check table t extended; +call check_table('t'); + +update t set x= 2147483647; +alter table t modify x bigint, algorithm=instant; +select * from t; +check table t extended; +call check_table('t'); + +--echo # Check IMPORT TABLESPACE +--let $MYSQLD_DATADIR= `select @@datadir` +create or replace table t2 (x int); +alter table t2 discard tablespace; + +create or replace table t1 (x tinyint); +insert into t1 set x= 42; +alter table t1 modify x int; +flush tables t1 for export; +--move_file $MYSQLD_DATADIR/test/t1.cfg $MYSQLD_DATADIR/test/t2.cfg +--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd +unlock tables; + +alter table t2 import tablespace; + +select * from t2; +check table t2 extended; +call check_table('t2'); + +--echo # Check innobase_col_to_mysql() len < flen +create or replace table t1 (x mediumint); +insert into t1 values (1); +insert into t1 values (1); +alter table t1 add column y int first, modify x int, algorithm instant; +--error ER_DUP_ENTRY +alter table t1 add column z int first, add primary key (x); + +--echo # Check assertion in wrong instant operation +create or replace table t1 (a varchar(26) not null) default character set utf8mb4; +alter table t1 modify a varchar(25) not null; + +--echo # Check row_mysql_store_col_in_innobase_format() +create or replace table t1(x int primary key, a varchar(20)); +insert into t1 (x) values (1); +update t1 set a= 'foo' where x = 2; + +--echo # +--echo # MDEV-18124 PK on inplace-enlarged type fails +--echo # +create or replace table t1 (x int, y int); +insert into t1 (x, y) values (11, 22); +alter table t1 modify x bigint, algorithm instant; +alter table t1 add primary key (x), algorithm inplace; +check table t1; + +create or replace table t1 (a varchar(10), y int); +insert into t1 (a, y) values ("0123456789", 33); +alter table t1 modify a char(15), algorithm instant; +alter table t1 add primary key (a), algorithm inplace; +check table t1; + +create or replace table t1 (x int primary key, y int); +insert into t1 (x, y) values (44, 55); +alter table t1 modify x bigint, algorithm inplace; +check table t1; + +create or replace table t1 (x int primary key, y int); +insert into t1 values (66, 77); +alter table t1 add column z int, algorithm instant; +alter table t1 drop column y, algorithm instant; + +create or replace table t1 (x integer, a varchar(20)); +alter table t1 add index idx3 (a); +insert into t1 (x, a) values (73, 'a'); +alter table t1 modify a char(20); + +create or replace database test charset latin1; +SET GLOBAL innodb_default_row_format=@save_format; diff --git a/sql/field.cc b/sql/field.cc index a19ff0a06d9..eef1061be4a 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7063,9 +7063,16 @@ uint Field::is_equal(Create_field *new_field) uint Field_str::is_equal(Create_field *new_field) { - return new_field->type_handler() == type_handler() && - new_field->charset == field_charset && - new_field->length == max_display_length(); + if (new_field->type_handler() == type_handler() && + new_field->charset == field_charset) + { + if (new_field->length == max_display_length()) + return IS_EQUAL_YES; + if (new_field->length > max_display_length() && + (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)) + return IS_EQUAL_PACK_LENGTH_EXT; + } + return IS_EQUAL_NO; } @@ -7904,19 +7911,26 @@ uint Field_varstring::is_equal(Create_field *new_field) if (new_field->length < field_length) return IS_EQUAL_NO; - if (new_field->type_handler() == type_handler() && - new_field->charset == field_charset && + if (new_field->charset == field_charset && !new_field->compression_method() == !compression_method()) { - if (new_field->length == field_length) - return IS_EQUAL_YES; - if (field_length <= 127 || - new_field->length <= 255 || - field_length > 255 || - (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)) - return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length + const Type_handler *new_type_handler= new_field->type_handler(); + if (new_type_handler == type_handler()) + { + if (new_field->length == field_length) + return IS_EQUAL_YES; + if (field_length <= 127 || + new_field->length <= 255 || + field_length > 255 || + (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)) + return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length + } + else if (new_type_handler == &type_handler_string) // converting to CHAR + { + if (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION) + return IS_EQUAL_PACK_LENGTH_EXT; + } } - return IS_EQUAL_NO; } @@ -9485,12 +9499,22 @@ bool Field_num::eq_def(const Field *field) const uint Field_num::is_equal(Create_field *new_field) { - return ((new_field->type_handler() == type_handler()) && - ((new_field->flags & UNSIGNED_FLAG) == - (uint) (flags & UNSIGNED_FLAG)) && - ((new_field->flags & AUTO_INCREMENT_FLAG) == - (uint) (flags & AUTO_INCREMENT_FLAG)) && - (new_field->pack_length == pack_length())); + if ((new_field->flags ^ flags) & (UNSIGNED_FLAG | AUTO_INCREMENT_FLAG)) + return IS_EQUAL_NO; + + const Type_handler *th= type_handler(), *new_th = new_field->type_handler(); + + if (th == new_th && new_field->pack_length == pack_length()) + return IS_EQUAL_YES; + + if (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION) + { + if (th->result_type() == new_th->result_type() && + new_field->pack_length >= pack_length()) + return IS_EQUAL_PACK_LENGTH_EXT; + } + + return IS_EQUAL_NO; } diff --git a/sql/field.h b/sql/field.h index e762e45c024..25d9f0e0ca4 100644 --- a/sql/field.h +++ b/sql/field.h @@ -4564,7 +4564,7 @@ public: :Type_handler_hybrid_field_type(&type_handler_null), compression_method_ptr(0), comment(null_clex_str), - on_update(NULL), invisible(VISIBLE), decimals(0), + on_update(NULL), invisible(VISIBLE), char_length(0), decimals(0), flags(0), pack_length(0), key_length(0), option_list(NULL), vcol_info(0), default_value(0), check_constraint(0), diff --git a/sql/handler.h b/sql/handler.h index be3aefb98d2..4fe6d981de1 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -746,6 +746,14 @@ typedef ulonglong alter_table_operations; */ #define ALTER_COLUMN_INDEX_LENGTH (1ULL << 60) +/** + Change the column length or type such that no rebuild is needed. + Only set if ALTER_COLUMN_EQUAL_PACK_LENGTH does not apply, and + if HA_EXTENDED_TYPES_CONVERSION holds. + @see IS_EQUAL_PACK_LENGTH_EXT +*/ +#define ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT (1ULL << 61) + /* Flags set in partition_flags when altering partitions */ diff --git a/sql/sql_priv.h b/sql/sql_priv.h index fa12b645041..d5a69d740ea 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2018, Oracle and/or its affiliates. - Copyright (c) 2010, 2018, Monty Program Ab. + Copyright (c) 2010, 2019, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -345,11 +345,21 @@ #ifndef MYSQL_CLIENT /* - Some defines for exit codes for ::is_equal class functions. + Field::is_equal() return codes. */ #define IS_EQUAL_NO 0 #define IS_EQUAL_YES 1 +/** + new_field has compatible packed representation with old type, + so it is theoretically possible to perform change by only updating + data dictionary without changing table rows +*/ #define IS_EQUAL_PACK_LENGTH 2 +/** + new_field has a representation that is compatible with the old type + when the storage engine advertises HA_EXTENDED_TYPES_CONVERSION +*/ +#define IS_EQUAL_PACK_LENGTH_EXT 3 enum enum_parsing_place { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8086950ea5b..24ba12b9323 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6615,6 +6615,9 @@ static bool fill_alter_inplace_info(THD *thd, */ ha_alter_info->handler_flags|= ALTER_COLUMN_EQUAL_PACK_LENGTH; break; + case IS_EQUAL_PACK_LENGTH_EXT: + ha_alter_info->handler_flags|= ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT; + break; default: DBUG_ASSERT(0); /* Safety. */ diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 29696f96aa0..2db08b1a537 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -4839,7 +4839,9 @@ n_field_mismatch: if (len_is_stored(len) && (field->prefix_len ? len > field->prefix_len - : (fixed_size && len != fixed_size))) { + : (fixed_size && (page_is_comp(page) + ? len != fixed_size + : len > fixed_size)))) { len_mismatch: btr_index_rec_validate_report(page, rec, index); ib::error error; diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 59704201c4e..ed9fd219d91 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -486,8 +486,14 @@ incompatible: For the metadata record, variable-length columns are always written with zero length. The DB_TRX_ID will start right after any fixed-length columns. */ - for (uint i = index->n_uniq; i--; ) { - trx_id_offset += index->fields[i].fixed_len; + if (index->table->not_redundant()) { + for (uint i = index->n_uniq; i--; ) { + trx_id_offset += index->fields[i] + .fixed_len; + } + } else { + trx_id_offset = rec_get_field_start_offs( + rec, index->n_uniq); } } diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 7664bc2064d..232a21b99d2 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -2203,6 +2203,14 @@ dict_index_too_big_for_tree( } field_max_size = dict_col_get_max_size(col); + if (!comp && (col->mtype == DATA_INT + || col->mtype == DATA_CHAR + || col->mtype == DATA_FIXBINARY)) { + /* DATA_INT, DATA_FIXBINARY and DATA_CHAR are variable- + length (enlarged instantly), but are stored locally. */ + field_ext_max_size = 0; + goto add_field_size; + } field_ext_max_size = field_max_size < 256 ? 1 : 2; if (field->prefix_len) { diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 50d0ad42094..c50d6e05fff 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -9967,7 +9967,7 @@ innobase_fts_create_doc_id_key( /* The unique Doc ID field should be an eight-bytes integer */ dict_field_t* field = dict_index_get_nth_field(index, 0); ut_a(field->col->mtype == DATA_INT); - ut_ad(sizeof(*doc_id) == field->fixed_len); + ut_ad(sizeof(*doc_id) == field->col->len); ut_ad(!strcmp(index->name, FTS_DOC_ID_INDEX_NAME)); #endif /* UNIV_DEBUG */ diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 4af97951570..30ca3975bf6 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -84,6 +84,7 @@ static const alter_table_operations INNOBASE_ALTER_REBUILD | ALTER_OPTIONS /* ALTER_OPTIONS needs to check alter_options_need_rebuild() */ | ALTER_COLUMN_NULLABLE + | ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT | INNOBASE_DEFAULTS | ALTER_STORED_COLUMN_ORDER | ALTER_DROP_STORED_COLUMN @@ -268,7 +269,7 @@ inline void dict_table_t::prepare_instant(const dict_table_t& old, ut_ad(!not_redundant()); for (unsigned i = index.n_fields; i--; ) { ut_ad(index.fields[i].col->same_format( - *oindex.fields[i].col)); + *oindex.fields[i].col, true)); } } #endif @@ -456,9 +457,13 @@ inline void dict_index_t::instant_add_field(const dict_index_t& instant) as this index. Fields for any added columns are appended at the end. */ #ifndef DBUG_OFF for (unsigned i = 0; i < n_fields; i++) { - DBUG_ASSERT(fields[i].same(instant.fields[i])); - DBUG_ASSERT(instant.fields[i].col->same_format(*fields[i] - .col)); + DBUG_ASSERT(fields[i].prefix_len + == instant.fields[i].prefix_len); + DBUG_ASSERT(fields[i].fixed_len + == instant.fields[i].fixed_len + || !table->not_redundant()); + DBUG_ASSERT(instant.fields[i].col->same_format( + *fields[i].col, !table->not_redundant())); /* Instant conversion from NULL to NOT NULL is not allowed. */ DBUG_ASSERT(!fields[i].col->is_nullable() || instant.fields[i].col->is_nullable()); @@ -534,10 +539,7 @@ inline bool dict_table_t::instant_column(const dict_table_t& table, if (const dict_col_t* o = find(old_cols, col_map, n_cols, i)) { c.def_val = o->def_val; - DBUG_ASSERT(!((c.prtype ^ o->prtype) - & ~(DATA_NOT_NULL | DATA_VERSIONED))); - DBUG_ASSERT(c.mtype == o->mtype); - DBUG_ASSERT(c.len >= o->len); + ut_ad(c.same_format(*o, !not_redundant())); if (o->vers_sys_start()) { ut_ad(o->ind == vers_start); @@ -1505,7 +1507,8 @@ instant_alter_column_possible( = ALTER_ADD_STORED_BASE_COLUMN | ALTER_DROP_STORED_COLUMN | ALTER_STORED_COLUMN_ORDER - | ALTER_COLUMN_NULLABLE; + | ALTER_COLUMN_NULLABLE + | ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT; if (!(ha_alter_info->handler_flags & avoid_rebuild)) { alter_table_operations flags = ha_alter_info->handler_flags @@ -1548,6 +1551,7 @@ instant_alter_column_possible( & ~ALTER_STORED_COLUMN_ORDER & ~ALTER_ADD_STORED_BASE_COLUMN & ~ALTER_COLUMN_NULLABLE + & ~ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT & ~ALTER_OPTIONS)) { return false; } @@ -1748,6 +1752,10 @@ ha_innobase::check_if_supported_inplace_alter( { DBUG_ENTER("check_if_supported_inplace_alter"); + DBUG_ASSERT(!(ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT + & ha_alter_info->handler_flags) + || !m_prebuilt->table->not_redundant()); + if ((ha_alter_info->handler_flags & INNOBASE_ALTER_VERSIONED_REBUILD) && altered_table->versioned(VERS_TIMESTAMP)) { @@ -2943,7 +2951,7 @@ innobase_col_to_mysql( switch (col->mtype) { case DATA_INT: - ut_ad(len == flen); + ut_ad(len <= flen); /* Convert integer data from Innobase to little-endian format, sign bit restored to normal */ @@ -5583,7 +5591,8 @@ static bool innobase_instant_try( bool update = old && (!ctx->first_alter_pos || i < ctx->first_alter_pos - 1); - DBUG_ASSERT(!old || col->same_format(*old)); + ut_ad(!old || col->same_format( + *old, !user_table->not_redundant())); if (update && old->prtype == d->type.prtype) { /* The record is already present in SYS_COLUMNS. */ @@ -5672,6 +5681,8 @@ add_all_virtual: NULL, trx, ctx->heap, NULL); dberr_t err = DB_SUCCESS; + DBUG_EXECUTE_IF("ib_instant_error", + err = DB_OUT_OF_FILE_SPACE; goto func_exit;); if (rec_is_metadata(rec, *index)) { ut_ad(page_rec_is_user_rec(rec)); if (!page_has_next(block->frame) @@ -9050,12 +9061,16 @@ innobase_enlarge_column_try( #ifdef UNIV_DEBUG ut_ad(col->len < new_len); switch (col->mtype) { + case DATA_FIXBINARY: + case DATA_CHAR: case DATA_MYSQL: /* NOTE: we could allow this when !(prtype & DATA_BINARY_TYPE) and ROW_FORMAT is not REDUNDANT and mbminlennot_redundant()) { + ut_error; + } case DATA_BINARY: case DATA_VARCHAR: case DATA_VARMYSQL: @@ -9188,14 +9203,16 @@ innobase_rename_or_enlarge_columns_cache( ulint col_n = is_virtual ? num_v : i - num_v; if ((*fp)->is_equal(cf) == IS_EQUAL_PACK_LENGTH) { - if (is_virtual) { - dict_table_get_nth_v_col( - user_table, col_n)->m_col.len - = cf->length; - } else { - dict_table_get_nth_col( - user_table, col_n)->len - = cf->length; + dict_col_t *col = is_virtual ? + &dict_table_get_nth_v_col( + user_table, col_n)->m_col + : dict_table_get_nth_col( + user_table, col_n); + col->len = cf->length; + if (col->len > 255 + && (col->prtype & DATA_MYSQL_TRUE_VARCHAR) + == DATA_MYSQL_TRUE_VARCHAR) { + col->prtype |= DATA_LONG_TRUE_VARCHAR; } } diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic index 56a588562ee..39f00364ea2 100644 --- a/storage/innobase/include/data0type.ic +++ b/storage/innobase/include/data0type.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -472,12 +472,18 @@ dtype_get_fixed_size_low( } #endif /* UNIV_DEBUG */ /* fall through */ - case DATA_CHAR: - case DATA_FIXBINARY: - case DATA_INT: case DATA_FLOAT: case DATA_DOUBLE: return(len); + case DATA_FIXBINARY: + case DATA_CHAR: + case DATA_INT: + /* Treat these types as variable length for redundant + row format. We can't rely on fixed_len anymore because record + can have shorter length from before instant enlargement + [MDEV-15563]. Note, that importing such tablespace to + earlier MariaDB versions produces ER_TABLE_SCHEMA_MISMATCH. */ + return comp ? len : 0; case DATA_MYSQL: if (prtype & DATA_BINARY_TYPE) { return(len); @@ -625,6 +631,14 @@ dtype_get_sql_null_size( const dtype_t* type, /*!< in: type */ ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ { + switch (type->mtype) { + case DATA_INT: + case DATA_CHAR: + case DATA_FIXBINARY: + return(type->len); + default: + break; + } return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, type->mbminlen, type->mbmaxlen, comp)); } diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 5f6cd3d13c5..3314b8e2459 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -685,15 +685,52 @@ public: /** Determine if the columns have the same format except for is_nullable() and is_versioned(). @param[in] other column to compare to + @param[in] redundant table is redundant row 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, bool redundant = false) const { - return mtype == other.mtype - && len >= other.len - && mbminlen == other.mbminlen - && mbmaxlen == other.mbmaxlen - && !((prtype ^ other.prtype) - & ~(DATA_NOT_NULL | DATA_VERSIONED)); + if (len < other.len + || mbminlen != other.mbminlen + || mbmaxlen != other.mbmaxlen) { + return false; + } + if (dtype_is_non_binary_string_type(mtype, prtype) + && dtype_is_non_binary_string_type(other.mtype, + other.prtype)) { + uint csn1 = (uint) dtype_get_charset_coll(prtype); + uint csn2 = (uint) dtype_get_charset_coll(other.prtype); + CHARSET_INFO* cs1 = get_charset(csn1, MYF(MY_WME)); + CHARSET_INFO* cs2 = get_charset(csn2, MYF(MY_WME)); + if (!my_charset_same(cs1, cs2)) { + return false; + } + } + + if (!((prtype ^ other.prtype) + & ~(DATA_NOT_NULL | DATA_VERSIONED))) { + return mtype == other.mtype; + } + + if (redundant) { + switch (other.mtype) { + case DATA_CHAR: + case DATA_MYSQL: + case DATA_VARCHAR: + case DATA_VARMYSQL: + return mtype == DATA_CHAR + || mtype == DATA_MYSQL + || mtype == DATA_VARCHAR + || mtype == DATA_VARMYSQL; + case DATA_FIXBINARY: + case DATA_BINARY: + return mtype == DATA_FIXBINARY + || mtype == DATA_BINARY; + case DATA_INT: + return mtype == DATA_INT; + } + } + + return false; } }; diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index f1776dd07ee..6de4dda93b1 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -706,11 +706,6 @@ row_merge_buf_add( row_field, field, col->len, old_table->space->zip_size(), conv_heap); - } else { - /* Field length mismatch should not - happen when rebuilding redundant row - format table. */ - ut_ad(dict_table_is_comp(index->table)); } } } diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 071ef9ffd92..1e82c6b6551 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -887,10 +887,15 @@ row_create_prebuilt( == MAX_REF_PARTS);); uint temp_len = 0; for (uint i = 0; i < temp_index->n_uniq; i++) { - ulint type = temp_index->fields[i].col->mtype; - if (type == DATA_INT) { - temp_len += - temp_index->fields[i].fixed_len; + const dict_field_t& f = temp_index->fields[i]; + if (f.col->mtype == DATA_INT) { + ut_ad(f.col->len >= f.fixed_len); + /* dtype_get_fixed_size_low() returns 0 + for ROW_FORMAT=REDUNDANT */ + ut_ad(table->not_redundant() + ? f.col->len == f.fixed_len + : f.fixed_len == 0); + temp_len += f.col->len; } } srch_key_len = std::max(srch_key_len,temp_len); diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 215ed0fe1e9..a03a4fa4acf 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -2742,12 +2742,15 @@ row_sel_field_store_in_mysql_format_func( dest[len - 1] = (byte) (dest[len - 1] ^ 128); } - ut_ad(templ->mysql_col_len == len); + ut_ad(templ->mysql_col_len == len + || !index->table->not_redundant()); break; case DATA_VARCHAR: case DATA_VARMYSQL: case DATA_BINARY: + case DATA_CHAR: + case DATA_FIXBINARY: field_end = dest + templ->mysql_col_len; if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) { @@ -2835,7 +2838,8 @@ row_sel_field_store_in_mysql_format_func( ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len || (field_no == templ->icp_rec_field_no && field->prefix_len > 0) - || templ->rec_field_is_prefix); + || templ->rec_field_is_prefix + || !index->table->not_redundant()); ut_ad(templ->is_virtual || !(field->prefix_len % templ->mbmaxlen)); @@ -2857,8 +2861,6 @@ row_sel_field_store_in_mysql_format_func( ut_ad(0); /* fall through */ - case DATA_CHAR: - case DATA_FIXBINARY: case DATA_FLOAT: case DATA_DOUBLE: case DATA_DECIMAL: From 62fad4e8e964786cd1c8d675f3c071a405a8d187 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 13 Feb 2019 08:55:38 -0800 Subject: [PATCH 79/91] MDEV-17096 Pushdown of simple derived tables to storage engines Fixing failures of federated test on 32-bit platforms --- storage/federatedx/ha_federatedx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index f55b0bc779d..b0a08a0d49a 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -3684,7 +3684,7 @@ struct st_mysql_storage_engine federatedx_storage_engine= my_bool use_pushdown; static MYSQL_SYSVAR_BOOL(pushdown, use_pushdown, 0, "Use query fragments pushdown capabilities", NULL, NULL, FALSE); -static struct st_mysql_sys_var* sysvars[]= { MYSQL_SYSVAR(pushdown) }; +static struct st_mysql_sys_var* sysvars[]= { MYSQL_SYSVAR(pushdown), NULL }; #include "federatedx_pushdown.cc" From 0f489494395a8cd6aeaf5943fea63a9e4465cabb Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 13 Feb 2019 19:39:41 +0200 Subject: [PATCH 80/91] MDEV-13916 Enforce check constraint on JSON type When creating a field of type JSON, it will be automatically converted to TEXT with CHECK (json_valid(`a`)), if there wasn't any previous check for the column. Additional things: - Added two bug fixes that was found while testing JSON. These bug fixes has also been pushed to 10.3 (with a test case), but as they where minimal and needed to get this task done and tested, the fixes are repeated here. - CREATE TABLE ... SELECT drops constraints for columns that are both in the create and select part. - If one has both a default expression and check constraint for a column, one can get the error "Expression for field `a` is refering to uninitialized field `a`. - Removed some duplicate MYSQL_PLUGIN_IMPORT symbols --- mysql-test/main/type_json.result | 67 ++++++++++++++++++++++++++++++-- mysql-test/main/type_json.test | 35 +++++++++++++++++ sql/field.cc | 1 + sql/sql_lex.cc | 18 +++++++++ sql/sql_lex.h | 7 ++++ sql/sql_type.cc | 1 + sql/sql_type.h | 15 ++++--- sql/sql_yacc.yy | 6 ++- sql/sql_yacc_ora.yy | 6 ++- sql/table.cc | 25 ++++++++---- 10 files changed, 163 insertions(+), 18 deletions(-) diff --git a/mysql-test/main/type_json.result b/mysql-test/main/type_json.result index 0045847097b..96e96cca404 100644 --- a/mysql-test/main/type_json.result +++ b/mysql-test/main/type_json.result @@ -2,7 +2,7 @@ create or replace table t1(a json); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL + `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`a`)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 create or replace table t1(a json character set utf8); 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 near 'character set utf8)' at line 1 @@ -10,7 +10,7 @@ create or replace table t1(a json default '{a:1}'); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '{a:1}' + `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '{a:1}' CHECK (json_valid(`a`)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 create or replace table t1(a json not null check (json_valid(a))); show create table t1; @@ -21,18 +21,79 @@ t1 CREATE TABLE `t1` ( insert t1 values ('[]'); insert t1 values ('a'); ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1` +create or replace table t1(a json not null); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`a`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +insert t1 values ('[]'); +insert t1 values ('a'); +ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1` set timestamp=unix_timestamp('2010:11:12 13:14:15'); create or replace table t1(a json default(json_object('now', now()))); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT json_object('now',current_timestamp()) + `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT json_object('now',current_timestamp()) CHECK (json_valid(`a`)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 insert t1 values (); select * from t1; a {"now": "2010-11-12 13:14:15"} drop table t1; +create table t1 (t json) as select json_quote('foo') as t; +create table t2 (a json) as select json_quote('foo') as t; +create table t3 like t1; +select * from t1; +t +"foo" +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`t`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`a`)), + `t` varchar(38) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`t`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1,t2,t3; +create table t1 (t json check (length(t) > 0)); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `t` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (octet_length(`t`) > 0) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; +create table t1 (t text) engine=myisam; +insert into t1 values ("{}"),(""); +create table t2 (t json) select t from t1; +ERROR 23000: CONSTRAINT `t2.t` failed for `test`.`t2` +select * from t2; +ERROR 42S02: Table 'test.t2' doesn't exist +drop table t1; +create or replace table t1(a json default(json_object('now', 1)) check (json_valid(a))); +insert into t1 values (); +insert into t1 values ("{}"); +insert into t1 values ("xxx"); +ERROR 23000: CONSTRAINT `t1.a` failed for `test`.`t1` +select * from t1; +a +{"now": 1} +{} +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT json_object('now',1) CHECK (json_valid(`a`)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +drop table t1; select cast('{a:1}' as text); 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 near 'text)' at line 1 select cast('{a:1}' as json); diff --git a/mysql-test/main/type_json.test b/mysql-test/main/type_json.test index 0cff9366145..bd13dc1fcf4 100644 --- a/mysql-test/main/type_json.test +++ b/mysql-test/main/type_json.test @@ -17,12 +17,47 @@ insert t1 values ('[]'); --error ER_CONSTRAINT_FAILED insert t1 values ('a'); +create or replace table t1(a json not null); +show create table t1; +insert t1 values ('[]'); +--error ER_CONSTRAINT_FAILED +insert t1 values ('a'); + set timestamp=unix_timestamp('2010:11:12 13:14:15'); create or replace table t1(a json default(json_object('now', now()))); show create table t1; insert t1 values (); select * from t1; +drop table t1; +create table t1 (t json) as select json_quote('foo') as t; +create table t2 (a json) as select json_quote('foo') as t; +create table t3 like t1; +select * from t1; +show create table t1; +show create table t2; +show create table t3; +drop table t1,t2,t3; + +create table t1 (t json check (length(t) > 0)); +show create table t1; +drop table t1; + +create table t1 (t text) engine=myisam; +insert into t1 values ("{}"),(""); +--error ER_CONSTRAINT_FAILED +create table t2 (t json) select t from t1; +--error ER_NO_SUCH_TABLE +select * from t2; +drop table t1; + +create or replace table t1(a json default(json_object('now', 1)) check (json_valid(a))); +insert into t1 values (); +insert into t1 values ("{}"); +--error ER_CONSTRAINT_FAILED +insert into t1 values ("xxx"); +select * from t1; +show create table t1; drop table t1; --error ER_PARSE_ERROR diff --git a/sql/field.cc b/sql/field.cc index eef1061be4a..6e45d10d855 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -10762,6 +10762,7 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field, interval= dup_field->interval; vcol_info= dup_field->vcol_info; invisible= dup_field->invisible; + check_constraint= dup_field->check_constraint; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 8e31f479d68..df45a2f201e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -9579,3 +9579,21 @@ bool LEX::sp_proc_stmt_statement_finalize(THD *thd, bool no_lookahead) lip->get_tok_start()); return LEX::sp_proc_stmt_statement_finalize_buf(thd, qbuf); } + + +/** + Create JSON_VALID(field_name) expression +*/ + +Virtual_column_info *make_json_valid_expr(THD *thd, LEX_CSTRING *field_name) +{ + Lex_ident_sys_st str; + Item *field, *expr; + str.set_valid_utf8(field_name); + if (unlikely(!(field= thd->lex->create_item_ident_field(thd, NullS, NullS, + &str)))) + return 0; + if (unlikely(!(expr= new (thd->mem_root) Item_func_json_valid(thd, field)))) + return 0; + return add_virtual_expression(thd, expr); +} diff --git a/sql/sql_lex.h b/sql/sql_lex.h index c22f95978a0..ed42c2efc72 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -148,6 +148,12 @@ public: bool copy_or_convert(THD *thd, const Lex_ident_cli_st *str, CHARSET_INFO *cs); bool is_null() const { return str == NULL; } bool to_size_number(ulonglong *to) const; + void set_valid_utf8(LEX_CSTRING *name) + { + DBUG_ASSERT(Well_formed_prefix(system_charset_info, name->str, + name->length).length() == name->length); + str= name->str ; length= name->length; + } }; @@ -4600,5 +4606,6 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, void sp_create_assignment_lex(THD *thd, bool no_lookahead); bool sp_create_assignment_instr(THD *thd, bool no_lookahead); +Virtual_column_info *make_json_valid_expr(THD *thd, LEX_CSTRING *field_name); #endif /* MYSQL_SERVER */ #endif /* SQL_LEX_INCLUDED */ diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 96a73a85267..6cccc785fee 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -66,6 +66,7 @@ Type_handler_tiny_blob type_handler_tiny_blob; Type_handler_medium_blob type_handler_medium_blob; Type_handler_long_blob type_handler_long_blob; Type_handler_blob type_handler_blob; +Type_handler_json type_handler_json; static Type_handler_blob_compressed type_handler_blob_compressed; Type_handler_interval_DDhhmmssff type_handler_interval_DDhhmmssff; diff --git a/sql/sql_type.h b/sql/sql_type.h index 3eb7d39742c..d507241075e 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3280,6 +3280,7 @@ public: return true; } virtual bool is_scalar_type() const { return true; } + virtual bool is_json_type() const { return false; } virtual bool can_return_int() const { return true; } virtual bool can_return_decimal() const { return true; } virtual bool can_return_real() const { return true; } @@ -5890,6 +5891,14 @@ public: }; +class Type_handler_json: public Type_handler_long_blob +{ +public: + virtual ~Type_handler_json() {} + virtual bool is_json_type() const { return true; } +}; + + class Type_handler_blob: public Type_handler_blob_common { static const Name m_name_blob; @@ -6218,6 +6227,7 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_hex_hybrid type_handler_hex_hybrid; extern MYSQL_PLUGIN_IMPORT Type_handler_tiny_blob type_handler_tiny_blob; extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob; extern MYSQL_PLUGIN_IMPORT Type_handler_long_blob type_handler_long_blob; +extern MYSQL_PLUGIN_IMPORT Type_handler_json type_handler_json; extern MYSQL_PLUGIN_IMPORT Type_handler_blob type_handler_blob; extern MYSQL_PLUGIN_IMPORT Type_handler_bool type_handler_bool; @@ -6243,11 +6253,6 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_datetime2 type_handler_datetime2; extern MYSQL_PLUGIN_IMPORT Type_handler_timestamp type_handler_timestamp; extern MYSQL_PLUGIN_IMPORT Type_handler_timestamp2 type_handler_timestamp2; -extern MYSQL_PLUGIN_IMPORT Type_handler_tiny_blob type_handler_tiny_blob; -extern MYSQL_PLUGIN_IMPORT Type_handler_blob type_handler_blob; -extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob; -extern MYSQL_PLUGIN_IMPORT Type_handler_long_blob type_handler_long_blob; - extern MYSQL_PLUGIN_IMPORT Type_handler_interval_DDhhmmssff type_handler_interval_DDhhmmssff; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 81ece13e1c5..2077ea52557 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6690,6 +6690,10 @@ field_spec: $$= $2; $$->check_constraint= $4; + if (!$4 && lex->last_field->type_handler()->is_json_type() && + !($$->check_constraint= make_json_valid_expr(thd, + &$$->field_name))) + MYSQL_YYABORT; if (unlikely($$->check(thd))) MYSQL_YYABORT; @@ -7083,7 +7087,7 @@ field_type_lob: | JSON_SYM { Lex->charset= &my_charset_utf8mb4_bin; - $$.set(&type_handler_long_blob); + $$.set(&type_handler_json); } ; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index aa622b61771..4e14be598ce 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -6628,6 +6628,10 @@ field_spec: $$= $2; $$->check_constraint= $4; + if (!$4 && lex->last_field->type_handler()->is_json_type() && + !($$->check_constraint= make_json_valid_expr(thd, + &$$->field_name))) + MYSQL_YYABORT; if (unlikely($$->check(thd))) MYSQL_YYABORT; @@ -7073,7 +7077,7 @@ field_type_lob: | JSON_SYM { Lex->charset= &my_charset_utf8mb4_bin; - $$.set(&type_handler_long_blob); + $$.set(&type_handler_json); } ; diff --git a/sql/table.cc b/sql/table.cc index d5c88b226c7..1ef216a2991 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -52,7 +52,8 @@ static Virtual_column_info * unpack_vcol_info_from_frm(THD *, MEM_ROOT *, TABLE *, String *, Virtual_column_info **, bool *); -static bool check_vcol_forward_refs(Field *, Virtual_column_info *); +static bool check_vcol_forward_refs(Field *, Virtual_column_info *, + bool check_constraint); /* INFORMATION_SCHEMA name */ LEX_CSTRING INFORMATION_SCHEMA_NAME= {STRING_WITH_LEN("information_schema")}; @@ -1189,9 +1190,9 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table, for (field_ptr= table->field; *field_ptr; field_ptr++) { Field *field= *field_ptr; - if (check_vcol_forward_refs(field, field->vcol_info) || - check_vcol_forward_refs(field, field->check_constraint) || - check_vcol_forward_refs(field, field->default_value)) + if (check_vcol_forward_refs(field, field->vcol_info, 0) || + check_vcol_forward_refs(field, field->check_constraint, 1) || + check_vcol_forward_refs(field, field->default_value, 0)) goto end; } @@ -3133,11 +3134,19 @@ end: DBUG_RETURN(vcol_info); } -static bool check_vcol_forward_refs(Field *field, Virtual_column_info *vcol) +static bool check_vcol_forward_refs(Field *field, Virtual_column_info *vcol, + bool check_constraint) { - bool res= vcol && - vcol->expr->walk(&Item::check_field_expression_processor, 0, - field); + bool res; + uint32 flags= field->flags; + if (check_constraint) + { + /* Check constraints can refer it itself */ + field->flags|= NO_DEFAULT_VALUE_FLAG; + } + res= (vcol && + vcol->expr->walk(&Item::check_field_expression_processor, 0, field)); + field->flags= flags; return res; } From 3e64e7f24c74da786e0f31bded61f59d9f772241 Mon Sep 17 00:00:00 2001 From: mkaruza Date: Tue, 12 Feb 2019 12:32:42 +0100 Subject: [PATCH 81/91] WSREP debug log levels support Global variable wsrep_debug now can be used to filter wsrep-lib messages based on debug level provided. Type of wsrep_debug is now set to be unsigned int, so tests and configuration files changed accordingly. --- include/mysql/service_wsrep.h | 2 +- .../suite/galera/r/galera_defaults.result | 2 +- .../suite/galera/t/galera_sst_mariabackup.cnf | 2 +- .../t/galera_sst_mariabackup_data_dir.cnf | 2 +- ...alera_sst_mariabackup_encrypt_with_key.cnf | 2 +- .../galera_sst_mariabackup_table_options.cnf | 2 +- .../t/galera_sst_mysqldump_with_key.cnf | 2 +- .../suite/sys_vars/r/sysvars_wsrep.result | 12 +++++----- .../suite/sys_vars/r/wsrep_debug_basic.result | 22 ++++++++++--------- .../suite/sys_vars/t/wsrep_debug_basic.test | 10 +++++---- sql/sys_vars.cc | 11 +++++++--- sql/wsrep_mysqld.cc | 3 ++- sql/wsrep_mysqld.h | 4 ++-- sql/wsrep_var.cc | 6 +++++ sql/wsrep_var.h | 2 ++ wsrep-lib | 2 +- 16 files changed, 52 insertions(+), 34 deletions(-) diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h index 5aa97cdb47e..2df497ec149 100644 --- a/include/mysql/service_wsrep.h +++ b/include/mysql/service_wsrep.h @@ -122,7 +122,7 @@ extern struct wsrep_service_st { #else #define MYSQL_SERVICE_WSREP_STATIC_INCLUDED -extern my_bool wsrep_debug; +extern ulong wsrep_debug; extern my_bool wsrep_log_conflicts; extern my_bool wsrep_certify_nonPK; extern my_bool wsrep_load_data_splitting; diff --git a/mysql-test/suite/galera/r/galera_defaults.result b/mysql-test/suite/galera/r/galera_defaults.result index 4aef4f5e48c..d0eb22ffcbc 100644 --- a/mysql-test/suite/galera/r/galera_defaults.result +++ b/mysql-test/suite/galera/r/galera_defaults.result @@ -26,7 +26,7 @@ WSREP_CLUSTER_ADDRESS gcomm:// WSREP_CLUSTER_NAME my_wsrep_cluster WSREP_CONVERT_LOCK_TO_TRX OFF WSREP_DBUG_OPTION -WSREP_DEBUG OFF +WSREP_DEBUG NONE WSREP_DESYNC OFF WSREP_DIRTY_READS OFF WSREP_DRUPAL_282555_WORKAROUND OFF diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup.cnf b/mysql-test/suite/galera/t/galera_sst_mariabackup.cnf index 336296e9bfe..be2ca0d1f09 100644 --- a/mysql-test/suite/galera/t/galera_sst_mariabackup.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup.cnf @@ -3,7 +3,7 @@ [mysqld] wsrep_sst_method=mariabackup wsrep_sst_auth="root:" -wsrep_debug=ON +wsrep_debug=1 [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_data_dir.cnf b/mysql-test/suite/galera/t/galera_sst_mariabackup_data_dir.cnf index aeb2301925e..b1caf700a12 100644 --- a/mysql-test/suite/galera/t/galera_sst_mariabackup_data_dir.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_data_dir.cnf @@ -3,7 +3,7 @@ [mysqld] wsrep_sst_method=mariabackup wsrep_sst_auth="root:" -wsrep_debug=ON +wsrep_debug=1 [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key.cnf b/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key.cnf index 646d7322b41..60db7ddba77 100644 --- a/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_encrypt_with_key.cnf @@ -3,7 +3,7 @@ [mysqld] wsrep_sst_method=mariabackup wsrep_sst_auth="root:" -wsrep_debug=ON +wsrep_debug=1 [SST] tkey=@ENV.MYSQL_TEST_DIR/std_data/cakey.pem diff --git a/mysql-test/suite/galera/t/galera_sst_mariabackup_table_options.cnf b/mysql-test/suite/galera/t/galera_sst_mariabackup_table_options.cnf index 336296e9bfe..be2ca0d1f09 100644 --- a/mysql-test/suite/galera/t/galera_sst_mariabackup_table_options.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mariabackup_table_options.cnf @@ -3,7 +3,7 @@ [mysqld] wsrep_sst_method=mariabackup wsrep_sst_auth="root:" -wsrep_debug=ON +wsrep_debug=1 [mysqld.1] wsrep_provider_options='base_port=@mysqld.1.#galera_port;gcache.size=1;pc.ignore_sb=true' diff --git a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf index b7bca487fc5..ebd116a359f 100644 --- a/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf +++ b/mysql-test/suite/galera/t/galera_sst_mysqldump_with_key.cnf @@ -14,7 +14,7 @@ wsrep_causal_reads=0 wsrep_sync_wait=0 [mysqld] -wsrep_debug=ON +wsrep_debug=1 [client] ssl-ca=@ENV.MYSQL_TEST_DIR/std_data/cacert.pem diff --git a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result index 49eaaa965dc..23a45f39896 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result +++ b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result @@ -115,18 +115,18 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME WSREP_DEBUG SESSION_VALUE NULL -GLOBAL_VALUE OFF +GLOBAL_VALUE NONE GLOBAL_VALUE_ORIGIN COMPILE-TIME -DEFAULT_VALUE OFF +DEFAULT_VALUE NONE VARIABLE_SCOPE GLOBAL -VARIABLE_TYPE BOOLEAN -VARIABLE_COMMENT To enable debug level logging +VARIABLE_TYPE ENUM +VARIABLE_COMMENT WSREP debug level logging NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -ENUM_VALUE_LIST OFF,ON +ENUM_VALUE_LIST NONE,SERVER,TRANSACTION,STREAMING,CLIENT READ_ONLY NO -COMMAND_LINE_ARGUMENT OPTIONAL +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME WSREP_DESYNC SESSION_VALUE NULL GLOBAL_VALUE OFF diff --git a/mysql-test/suite/sys_vars/r/wsrep_debug_basic.result b/mysql-test/suite/sys_vars/r/wsrep_debug_basic.result index 96c262c110c..47d00f5dede 100644 --- a/mysql-test/suite/sys_vars/r/wsrep_debug_basic.result +++ b/mysql-test/suite/sys_vars/r/wsrep_debug_basic.result @@ -6,39 +6,41 @@ SET @wsrep_debug_global_saved = @@global.wsrep_debug; # default SELECT @@global.wsrep_debug; @@global.wsrep_debug -0 +NONE # scope SELECT @@session.wsrep_debug; ERROR HY000: Variable 'wsrep_debug' is a GLOBAL variable -SET @@global.wsrep_debug=OFF; +SET @@global.wsrep_debug=0; SELECT @@global.wsrep_debug; @@global.wsrep_debug -0 -SET @@global.wsrep_debug=ON; +NONE +SET @@global.wsrep_debug=1; SELECT @@global.wsrep_debug; @@global.wsrep_debug -1 +SERVER # valid values -SET @@global.wsrep_debug='OFF'; +SET @@global.wsrep_debug=NONE; SELECT @@global.wsrep_debug; @@global.wsrep_debug -0 -SET @@global.wsrep_debug=ON; +NONE +SET @@global.wsrep_debug=SERVER; SELECT @@global.wsrep_debug; @@global.wsrep_debug -1 +SERVER SET @@global.wsrep_debug=default; SELECT @@global.wsrep_debug; @@global.wsrep_debug -0 +NONE # invalid values SET @@global.wsrep_debug=NULL; ERROR 42000: Variable 'wsrep_debug' can't be set to the value of 'NULL' SET @@global.wsrep_debug='junk'; ERROR 42000: Variable 'wsrep_debug' can't be set to the value of 'junk' +SET @@global.wsrep_debug=ON; +ERROR 42000: Variable 'wsrep_debug' can't be set to the value of 'ON' # restore the initial value SET @@global.wsrep_debug = @wsrep_debug_global_saved; diff --git a/mysql-test/suite/sys_vars/t/wsrep_debug_basic.test b/mysql-test/suite/sys_vars/t/wsrep_debug_basic.test index 50576ff064e..165560bb25a 100644 --- a/mysql-test/suite/sys_vars/t/wsrep_debug_basic.test +++ b/mysql-test/suite/sys_vars/t/wsrep_debug_basic.test @@ -14,16 +14,16 @@ SELECT @@global.wsrep_debug; --echo # scope --error ER_INCORRECT_GLOBAL_LOCAL_VAR SELECT @@session.wsrep_debug; -SET @@global.wsrep_debug=OFF; +SET @@global.wsrep_debug=0; SELECT @@global.wsrep_debug; -SET @@global.wsrep_debug=ON; +SET @@global.wsrep_debug=1; SELECT @@global.wsrep_debug; --echo --echo # valid values -SET @@global.wsrep_debug='OFF'; +SET @@global.wsrep_debug=NONE; SELECT @@global.wsrep_debug; -SET @@global.wsrep_debug=ON; +SET @@global.wsrep_debug=SERVER; SELECT @@global.wsrep_debug; SET @@global.wsrep_debug=default; SELECT @@global.wsrep_debug; @@ -34,6 +34,8 @@ SELECT @@global.wsrep_debug; SET @@global.wsrep_debug=NULL; --error ER_WRONG_VALUE_FOR_VAR SET @@global.wsrep_debug='junk'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_debug=ON; --echo --echo # restore the initial value diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index ad576280d3d..09a3de37c70 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5364,9 +5364,14 @@ static Sys_var_charptr Sys_wsrep_dbug_option( GLOBAL_VAR(wsrep_dbug_option),CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, DEFAULT("")); -static Sys_var_mybool Sys_wsrep_debug( - "wsrep_debug", "To enable debug level logging", - GLOBAL_VAR(wsrep_debug), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); +static const char *wsrep_debug_names[]= +{ "NONE", "SERVER", "TRANSACTION", "STREAMING", "CLIENT", NullS }; +static Sys_var_enum Sys_wsrep_debug( + "wsrep_debug", "WSREP debug level logging", + GLOBAL_VAR(wsrep_debug), CMD_LINE(REQUIRED_ARG), + wsrep_debug_names, DEFAULT(0), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(0), ON_UPDATE(wsrep_debug_update)); static Sys_var_mybool Sys_wsrep_convert_LOCK_to_trx( "wsrep_convert_LOCK_to_trx", "To convert locking sessions " diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 06e713ceda0..18c2e7072e2 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -85,7 +85,7 @@ const char *wsrep_data_home_dir; const char *wsrep_dbug_option; const char *wsrep_notify_cmd; -my_bool wsrep_debug; // Enable debug level logging +ulong wsrep_debug; // Debug level logging my_bool wsrep_convert_LOCK_to_trx; // Convert locking sessions to trx my_bool wsrep_auto_increment_control; // Control auto increment variables my_bool wsrep_drupal_282555_workaround; // Retry autoinc insert after dupkey @@ -638,6 +638,7 @@ int wsrep_init_server() working_dir, initial_position, wsrep_max_protocol_version); + Wsrep_server_state::instance().debug_log_level(wsrep_debug); } catch (const wsrep::runtime_error& e) { diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 3c430ccf487..9cf998c8afd 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -64,7 +64,7 @@ extern const char* wsrep_data_home_dir; extern const char* wsrep_dbug_option; extern long wsrep_slave_threads; extern int wsrep_slave_count_change; -extern MYSQL_PLUGIN_IMPORT my_bool wsrep_debug; +extern ulong wsrep_debug; extern my_bool wsrep_convert_LOCK_to_trx; extern ulong wsrep_retry_autocommit; extern my_bool wsrep_auto_increment_control; @@ -75,7 +75,7 @@ extern ulong wsrep_max_ws_size; extern ulong wsrep_max_ws_rows; extern const char* wsrep_notify_cmd; extern my_bool wsrep_certify_nonPK; -extern long int wsrep_protocol_version; +extern long int wsrep_protocol_version; extern ulong wsrep_forced_binlog_format; extern my_bool wsrep_desync; extern ulong wsrep_reject_queries; diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 8a0968639c2..7ba4ed3c14c 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -430,6 +430,12 @@ bool wsrep_reject_queries_update(sys_var *self, THD* thd, enum_var_type type) return false; } +bool wsrep_debug_update(sys_var *self, THD* thd, enum_var_type type) +{ + Wsrep_server_state::instance().debug_log_level(wsrep_debug); + return false; +} + static int wsrep_cluster_address_verify (const char* cluster_address_str) { /* There is no predefined address format, it depends on provider. */ diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index b732fb48b38..0acb61432f0 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -100,6 +100,8 @@ extern bool wsrep_max_ws_size_update UPDATE_ARGS; extern bool wsrep_reject_queries_update UPDATE_ARGS; +extern bool wsrep_debug_update UPDATE_ARGS; + #else /* WITH_WSREP */ #define wsrep_provider_init(X) diff --git a/wsrep-lib b/wsrep-lib index 20b52ff1ddc..af8383daf03 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit 20b52ff1ddc3b2f547b7081471f46dcfa5efabc7 +Subproject commit af8383daf03bee80b8e54ce207fa9ef1f9d83f94 From a081a998a62eb0663b5691d0b5c0607465f15c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 13 Feb 2019 22:06:30 +0200 Subject: [PATCH 82/91] MDEV-15563: Fix cmake -DPLUGIN_PERFSCHEMA=NO Commit 22feb179ae166500ec91feec6246c8154e33f9a2 broke the build with performance_schema disabled. dict_col_t::same_charset(): An auxiliary function to dict_col_t::same_format(). Determine if two non-binary string columns have the same character set. --- storage/innobase/data/data0type.cc | 21 +++++++++++++++++++-- storage/innobase/include/dict0mem.h | 27 ++++++++++++--------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/storage/innobase/data/data0type.cc b/storage/innobase/data/data0type.cc index 84962d097aa..0e07ca5182b 100644 --- a/storage/innobase/data/data0type.cc +++ b/storage/innobase/data/data0type.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -24,7 +24,8 @@ Data types Created 1/16/1996 Heikki Tuuri *******************************************************/ -#include "data0type.h" +#include "dict0mem.h" +#include "my_sys.h" /** The DB_TRX_ID,DB_ROLL_PTR values for "no history is available" */ const byte reset_trx_id[DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN] = { @@ -160,6 +161,22 @@ dtype_validate( return(TRUE); } +bool dict_col_t::same_charset(const dict_col_t& other) const +{ + if (dtype_is_non_binary_string_type(mtype, prtype) + && dtype_is_non_binary_string_type(other.mtype, other.prtype)) { + uint csn1 = (uint) dtype_get_charset_coll(prtype); + uint csn2 = (uint) dtype_get_charset_coll(other.prtype); + CHARSET_INFO* cs1 = get_charset(csn1, MYF(MY_WME)); + CHARSET_INFO* cs2 = get_charset(csn2, MYF(MY_WME)); + if (!my_charset_same(cs1, cs2)) { + return false; + } + } + + return true; +} + #ifdef UNIV_DEBUG /** Print a data type structure. @param[in] type data type */ diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 3314b8e2459..e9ffa660354 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -682,6 +682,12 @@ public: def_val.data = NULL; } +private: + /** Determine if the columns have the same character set + @param[in] other column to compare to + @return whether the columns have the same character set */ + bool same_charset(const dict_col_t& other) const; +public: /** Determine if the columns have the same format except for is_nullable() and is_versioned(). @param[in] other column to compare to @@ -694,17 +700,6 @@ public: || mbmaxlen != other.mbmaxlen) { return false; } - if (dtype_is_non_binary_string_type(mtype, prtype) - && dtype_is_non_binary_string_type(other.mtype, - other.prtype)) { - uint csn1 = (uint) dtype_get_charset_coll(prtype); - uint csn2 = (uint) dtype_get_charset_coll(other.prtype); - CHARSET_INFO* cs1 = get_charset(csn1, MYF(MY_WME)); - CHARSET_INFO* cs2 = get_charset(csn2, MYF(MY_WME)); - if (!my_charset_same(cs1, cs2)) { - return false; - } - } if (!((prtype ^ other.prtype) & ~(DATA_NOT_NULL | DATA_VERSIONED))) { @@ -717,14 +712,16 @@ public: case DATA_MYSQL: case DATA_VARCHAR: case DATA_VARMYSQL: - return mtype == DATA_CHAR + return (mtype == DATA_CHAR || mtype == DATA_MYSQL || mtype == DATA_VARCHAR - || mtype == DATA_VARMYSQL; + || mtype == DATA_VARMYSQL) + && same_charset(other); case DATA_FIXBINARY: case DATA_BINARY: - return mtype == DATA_FIXBINARY - || mtype == DATA_BINARY; + return (mtype == DATA_FIXBINARY + || mtype == DATA_BINARY) + && same_charset(other); case DATA_INT: return mtype == DATA_INT; } From 047754a72848aaec223d59115af6401cbef4a4fb Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Wed, 23 Jan 2019 11:33:56 +0100 Subject: [PATCH 83/91] Cleanup wsrep_schema and remove all references to wsrep_thd_pool * Removed all references related to wsrep_thd_pool (which was removed) * Removed unused declarations in wsrep_schema.h * The following would result invalid reads in Wsrep_schema::replay_transaction(): ``` frag_table->field[4]->val_str(&buf); Wsrep_schema_impl::end_index_scan(frag_table); Wsrep_schema_impl::finish_stmt(thd); ret= wsrep_apply_events(thd, rli, buf.c_ptr_safe(), buf.length()); ``` because `buf` was accessed after closing the table. The fix is to perform storage reads using a different THD. * In Wsrep_schema::recover_sr_transactions(), cluster_table was opened for write, however it is only read here. And frag_table was opened for read, wereas write is potentially needed. Also, avoid copy caused by String::c_ptr() to zero terminate the c string, use c_ptr_quick instead. --- sql/wsrep_mysqld.h | 2 -- sql/wsrep_schema.cc | 81 +++++++++++++++++++++++++-------------------- sql/wsrep_schema.h | 19 +---------- 3 files changed, 47 insertions(+), 55 deletions(-) diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 3c430ccf487..4bf1d1d60a2 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -303,7 +303,6 @@ extern mysql_mutex_t LOCK_wsrep_slave_threads; extern mysql_mutex_t LOCK_wsrep_desync; extern mysql_mutex_t LOCK_wsrep_SR_pool; extern mysql_mutex_t LOCK_wsrep_SR_store; -extern mysql_mutex_t LOCK_wsrep_thd_pool; extern mysql_mutex_t LOCK_wsrep_config_state; extern my_bool wsrep_emulate_bin_log; extern int wsrep_to_isolation; @@ -330,7 +329,6 @@ extern PSI_mutex_key key_LOCK_wsrep_slave_threads; extern PSI_mutex_key key_LOCK_wsrep_desync; extern PSI_mutex_key key_LOCK_wsrep_SR_pool; extern PSI_mutex_key key_LOCK_wsrep_SR_store; -extern PSI_mutex_key key_LOCK_wsrep_thd_pool; extern PSI_mutex_key key_LOCK_wsrep_global_seqno; extern PSI_mutex_key key_LOCK_wsrep_thd_queue; extern PSI_cond_key key_COND_wsrep_thd_queue; diff --git a/sql/wsrep_schema.cc b/sql/wsrep_schema.cc index 98f17e41c94..57b116e899c 100644 --- a/sql/wsrep_schema.cc +++ b/sql/wsrep_schema.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2017 Codership Oy +/* Copyright (C) 2015-2019 Codership Oy 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 @@ -584,8 +584,6 @@ static void wsrep_init_thd_for_schema(THD *thd) thd->real_id=pthread_self(); // Keep purify happy - WSREP_DEBUG("Wsrep_thd_pool: creating system thread: %lld", - (long long)thd->thread_id); thd->prior_thr_create_utime= thd->start_utime= thd->thr_create_utime; (void) mysql_mutex_unlock(&LOCK_thread_count); @@ -1115,7 +1113,7 @@ int Wsrep_schema::remove_fragments(THD* thd, DBUG_RETURN(ret); } -int Wsrep_schema::replay_transaction(THD* thd, +int Wsrep_schema::replay_transaction(THD* orig_thd, Relay_log_info* rli, const wsrep::ws_meta& ws_meta, const std::vector& fragments) @@ -1123,8 +1121,13 @@ int Wsrep_schema::replay_transaction(THD* thd, DBUG_ENTER("Wsrep_schema::replay_transaction"); DBUG_ASSERT(!fragments.empty()); - Wsrep_schema_impl::wsrep_off wsrep_off(thd); - Wsrep_schema_impl::binlog_off binlog_off(thd); + THD thd(next_thread_id(), true); + thd.thread_stack= (orig_thd ? orig_thd->thread_stack : + (char*) &thd); + + Wsrep_schema_impl::wsrep_off wsrep_off(&thd); + Wsrep_schema_impl::binlog_off binlog_off(&thd); + Wsrep_schema_impl::thd_context_switch thd_context_switch(orig_thd, &thd); int ret= 1; int error; @@ -1135,11 +1138,11 @@ int Wsrep_schema::replay_transaction(THD* thd, for (std::vector::const_iterator i= fragments.begin(); i != fragments.end(); ++i) { - Wsrep_schema_impl::init_stmt(thd); - if ((error= Wsrep_schema_impl::open_for_read(thd, sr_table_str.c_str(), &frag_table))) + Wsrep_schema_impl::init_stmt(&thd); + if ((error= Wsrep_schema_impl::open_for_read(&thd, sr_table_str.c_str(), &frag_table))) { WSREP_WARN("Could not open SR table for read: %d", error); - Wsrep_schema_impl::finish_stmt(thd); + Wsrep_schema_impl::finish_stmt(&thd); DBUG_RETURN(1); } @@ -1169,20 +1172,28 @@ int Wsrep_schema::replay_transaction(THD* thd, String buf; frag_table->field[4]->val_str(&buf); - Wsrep_schema_impl::end_index_scan(frag_table); - Wsrep_schema_impl::finish_stmt(thd); - ret= wsrep_apply_events(thd, rli, buf.c_ptr_safe(), buf.length()); - if (ret) { - WSREP_WARN("Wsrep_schema::replay_transaction: failed to apply fragments"); - break; - } - Wsrep_schema_impl::init_stmt(thd); + Wsrep_schema_impl::thd_context_switch thd_context_switch(&thd, orig_thd); - if ((error= Wsrep_schema_impl::open_for_write(thd, sr_table_str.c_str(), &frag_table))) + ret= wsrep_apply_events(orig_thd, rli, buf.c_ptr_quick(), buf.length()); + if (ret) + { + WSREP_WARN("Wsrep_schema::replay_transaction: failed to apply fragments"); + break; + } + } + + Wsrep_schema_impl::end_index_scan(frag_table); + Wsrep_schema_impl::finish_stmt(&thd); + + Wsrep_schema_impl::init_stmt(&thd); + + if ((error= Wsrep_schema_impl::open_for_write(&thd, + sr_table_str.c_str(), + &frag_table))) { WSREP_WARN("Could not open SR table for write: %d", error); - Wsrep_schema_impl::finish_stmt(thd); + Wsrep_schema_impl::finish_stmt(&thd); DBUG_RETURN(1); } error= Wsrep_schema_impl::init_for_index_scan(frag_table, @@ -1206,7 +1217,7 @@ int Wsrep_schema::replay_transaction(THD* thd, break; } Wsrep_schema_impl::end_index_scan(frag_table); - Wsrep_schema_impl::finish_stmt(thd); + Wsrep_schema_impl::finish_stmt(&thd); } DBUG_RETURN(ret); @@ -1215,14 +1226,14 @@ int Wsrep_schema::replay_transaction(THD* thd, int Wsrep_schema::recover_sr_transactions(THD *orig_thd) { DBUG_ENTER("Wsrep_schema::recover_sr_transactions"); - THD storage_thd(true, true); + THD storage_thd(next_thread_id(), true); storage_thd.thread_stack= (orig_thd ? orig_thd->thread_stack : (char*) &storage_thd); TABLE* frag_table= 0; TABLE* cluster_table= 0; Wsrep_storage_service storage_service(&storage_thd); Wsrep_schema_impl::binlog_off binlog_off(&storage_thd); - Wsrep_schema_impl::wsrep_off binglog_off(&storage_thd); + Wsrep_schema_impl::wsrep_off wsrep_off(&storage_thd); Wsrep_schema_impl::thd_context_switch thd_context_switch(orig_thd, &storage_thd); Wsrep_server_state& server_state(Wsrep_server_state::instance()); @@ -1233,13 +1244,9 @@ int Wsrep_schema::recover_sr_transactions(THD *orig_thd) Wsrep_schema_impl::init_stmt(&storage_thd); storage_thd.wsrep_skip_locking= FALSE; - /* - Open the table for reading and writing so that fragments without - valid seqno can be deleted. - */ - if (Wsrep_schema_impl::open_for_write(&storage_thd, - cluster_table_str.c_str(), - &cluster_table) || + if (Wsrep_schema_impl::open_for_read(&storage_thd, + cluster_table_str.c_str(), + &cluster_table) || Wsrep_schema_impl::init_for_scan(cluster_table)) { Wsrep_schema_impl::finish_stmt(&storage_thd); @@ -1273,10 +1280,15 @@ int Wsrep_schema::recover_sr_transactions(THD *orig_thd) storage_thd.wsrep_skip_locking= TRUE; Wsrep_schema_impl::init_stmt(&storage_thd); - if (Wsrep_schema_impl::open_for_read(&storage_thd, sr_table_str.c_str(), &frag_table) || + + /* + Open the table for reading and writing so that fragments without + valid seqno can be deleted. + */ + if (Wsrep_schema_impl::open_for_write(&storage_thd, sr_table_str.c_str(), &frag_table) || Wsrep_schema_impl::init_for_scan(frag_table)) { - WSREP_ERROR("Failed to open SR table for read"); + WSREP_ERROR("Failed to open SR table for write"); goto out; } @@ -1309,7 +1321,7 @@ int Wsrep_schema::recover_sr_transactions(THD *orig_thd) String data_str; (void)frag_table->field[4]->val_str(&data_str); - wsrep::const_buffer data(data_str.c_ptr(), data_str.length()); + wsrep::const_buffer data(data_str.c_ptr_quick(), data_str.length()); wsrep::ws_meta ws_meta(gtid, wsrep::stid(server_id, transaction_id, @@ -1319,14 +1331,13 @@ int Wsrep_schema::recover_sr_transactions(THD *orig_thd) wsrep::high_priority_service* applier; if (!(applier= server_state.find_streaming_applier(server_id, - transaction_id))) + transaction_id))) { DBUG_ASSERT(wsrep::starts_transaction(flags)); - THD* thd= new THD(true, true); + THD* thd= new THD(next_thread_id(), true); thd->thread_stack= (char*)&storage_thd; mysql_mutex_lock(&LOCK_thread_count); - thd->thread_id= next_thread_id(); thd->real_id= pthread_self(); mysql_mutex_unlock(&LOCK_thread_count); diff --git a/sql/wsrep_schema.h b/sql/wsrep_schema.h index fb5eaa8931f..36e23998d19 100644 --- a/sql/wsrep_schema.h +++ b/sql/wsrep_schema.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015-2018 Codership Oy +/* Copyright (C) 2015-2019 Codership Oy 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 @@ -20,13 +20,9 @@ /* wsrep-lib */ #include "wsrep_types.h" - #include "mysqld.h" -#include "thr_lock.h" /* enum thr_lock_type */ #include "wsrep_mysqld.h" -#include - /* Forward decls */ @@ -64,14 +60,6 @@ class Wsrep_schema */ Wsrep_view restore_view(THD* thd, const Wsrep_id& own_id) const; - /* - Append transaction fragment to fragment storage. - Starts a trx using a THD from thd_pool, does not commit. - Should be followed by a call to update_frag_seqno(), or - release_SR_thd() if wsrep->certify() fails. - */ - THD* append_frag(const wsrep_trx_meta_t&, uint32_t, - const unsigned char*, size_t); /** Append transaction fragment to fragment storage. Transaction must have been started for THD before this call. @@ -145,11 +133,6 @@ class Wsrep_schema */ int recover_sr_transactions(THD* orig_thd); - /* - Close wsrep schema. - */ - void close(); - private: /* Non-copyable */ Wsrep_schema(const Wsrep_schema&); From 1d8b5524f4a985c67a81742dbbbb8bbc8549d7ee Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 13 Feb 2019 14:26:02 +0100 Subject: [PATCH 84/91] cleanup: remove THD::query_start_timeval() Too easy to abuse. One tends to use it even when microseconds are not needed and will be ignored. --- sql/field.cc | 7 ++++++- sql/sql_class.h | 4 ---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index 6e45d10d855..de34b681a28 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -6796,7 +6796,12 @@ int Field_datetime::set_time() THD *thd= table->in_use; set_notnull(); // Here we always truncate (not round), no matter what sql_mode is - store_datetime(Datetime(thd, thd->query_start_timeval()).trunc(decimals())); + if (decimals()) + store_datetime(Datetime(thd, Timeval(thd->query_start(), + thd->query_start_sec_part()) + ).trunc(decimals())); + else + store_datetime(Datetime(thd, Timeval(thd->query_start(), 0))); return 0; } diff --git a/sql/sql_class.h b/sql/sql_class.h index d6da0566bbe..1fc4f375b6c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3455,10 +3455,6 @@ public: inline ulong query_start_sec_part() { query_start_sec_part_used=1; return start_time_sec_part; } MYSQL_TIME query_start_TIME(); - Timeval query_start_timeval() - { - return Timeval(query_start(), query_start_sec_part()); - } time_round_mode_t temporal_round_mode() const { return variables.sql_mode & MODE_TIME_ROUND_FRACTIONAL ? From c0745e3730a28a1c22d7e6b250b93377efed90f2 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 13 Feb 2019 18:01:45 +0100 Subject: [PATCH 85/91] bugfix: CREATE...SELECT lost COMMENT and VERSIONING --- mysql-test/main/create_select_tmp.result | 21 +++++++++++++++++++++ mysql-test/main/create_select_tmp.test | 14 ++++++++++++++ sql/field.cc | 3 +++ 3 files changed, 38 insertions(+) diff --git a/mysql-test/main/create_select_tmp.result b/mysql-test/main/create_select_tmp.result index f499e539baf..2842ab26c42 100644 --- a/mysql-test/main/create_select_tmp.result +++ b/mysql-test/main/create_select_tmp.result @@ -18,3 +18,24 @@ ERROR 23000: Duplicate entry '1' for key 'PRIMARY' select * from t2; ERROR 42S02: Table 'test.t2' doesn't exist drop table t1; +set sql_mode='ignore_bad_table_options'; +create table t1 ( +f1 int invisible, +f2 int comment 'a comment', +f3 int foo="bar", +f4 int check(f4 < 10), +f5 int without system versioning +) with system versioning as select 1 as f1,2 as f2,3 as f3,4 as f4,5 as f5; +Warnings: +Warning 1911 Unknown option 'foo' +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) INVISIBLE DEFAULT NULL, + `f2` int(11) DEFAULT NULL COMMENT 'a comment', + `f3` int(11) DEFAULT NULL `foo`='bar', + `f4` int(11) DEFAULT NULL CHECK (`f4` < 10), + `f5` int(11) DEFAULT NULL WITHOUT SYSTEM VERSIONING +) ENGINE=MyISAM DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING +drop table t1; +set sql_mode=default; diff --git a/mysql-test/main/create_select_tmp.test b/mysql-test/main/create_select_tmp.test index ef3315aed97..3ed885ea382 100644 --- a/mysql-test/main/create_select_tmp.test +++ b/mysql-test/main/create_select_tmp.test @@ -37,3 +37,17 @@ select * from t2; drop table t1; # End of 4.1 tests + +set sql_mode='ignore_bad_table_options'; +create table t1 ( + f1 int invisible, + f2 int comment 'a comment', + f3 int foo="bar", + f4 int check(f4 < 10), + f5 int without system versioning +) with system versioning as select 1 as f1,2 as f2,3 as f3,4 as f4,5 as f5; +show create table t1; +drop table t1; +set sql_mode=default; + +# End of 10.4 tests diff --git a/sql/field.cc b/sql/field.cc index de34b681a28..34f650b8a75 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -10768,6 +10768,9 @@ Column_definition::redefine_stage1_common(const Column_definition *dup_field, vcol_info= dup_field->vcol_info; invisible= dup_field->invisible; check_constraint= dup_field->check_constraint; + comment= dup_field->comment; + option_list= dup_field->option_list; + versioning= dup_field->versioning; } From 84cbd69c9ea597d45a83632bcb3def75d66c62ad Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 13 Feb 2019 18:02:02 +0100 Subject: [PATCH 86/91] cleanup: reformat --- sql/sql_insert.cc | 6 ++---- sql/sql_table.cc | 32 +++++++++++--------------------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a8f074e1783..b56fa44d8fd 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4147,10 +4147,8 @@ Field *Item::create_field_for_create_select(TABLE *table) @retval 0 Error */ -TABLE *select_create::create_table_from_items(THD *thd, - List *items, - MYSQL_LOCK **lock, - TABLEOP_HOOKS *hooks) +TABLE *select_create::create_table_from_items(THD *thd, List *items, + MYSQL_LOCK **lock, TABLEOP_HOOKS *hooks) { TABLE tmp_table; // Used during 'Create_field()' TABLE_SHARE share; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 24ba12b9323..a40febf58f4 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4438,12 +4438,11 @@ static bool vers_prepare_keys(THD *thd, HA_CREATE_INFO *create_info, return false; } -handler *mysql_create_frm_image(THD *thd, - const LEX_CSTRING *db, const LEX_CSTRING *table_name, +handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING *db, + const LEX_CSTRING *table_name, HA_CREATE_INFO *create_info, Alter_info *alter_info, int create_table_mode, - KEY **key_info, - uint *key_count, + KEY **key_info, uint *key_count, LEX_CUSTRING *frm) { uint db_options; @@ -4681,8 +4680,7 @@ handler *mysql_create_frm_image(THD *thd, } if (mysql_prepare_create_table(thd, create_info, alter_info, &db_options, - file, key_info, key_count, - create_table_mode)) + file, key_info, key_count, create_table_mode)) goto err; create_info->table_options=db_options; @@ -4734,19 +4732,13 @@ err: */ static -int create_table_impl(THD *thd, - const LEX_CSTRING *orig_db, +int create_table_impl(THD *thd, const LEX_CSTRING *orig_db, const LEX_CSTRING *orig_table_name, const LEX_CSTRING *db, const LEX_CSTRING *table_name, - const char *path, - const DDL_options_st options, - HA_CREATE_INFO *create_info, - Alter_info *alter_info, - int create_table_mode, - bool *is_trans, - KEY **key_info, - uint *key_count, - LEX_CUSTRING *frm) + const char *path, const DDL_options_st options, + HA_CREATE_INFO *create_info, Alter_info *alter_info, + int create_table_mode, bool *is_trans, KEY **key_info, + uint *key_count, LEX_CUSTRING *frm) { LEX_CSTRING *alias; handler *file= 0; @@ -5026,13 +5018,11 @@ warn: -1 Table was used with IF NOT EXISTS and table existed (warning, not error) */ -int mysql_create_table_no_lock(THD *thd, - const LEX_CSTRING *db, +int mysql_create_table_no_lock(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table_name, Table_specification_st *create_info, Alter_info *alter_info, bool *is_trans, - int create_table_mode, - TABLE_LIST *table_list) + int create_table_mode, TABLE_LIST *table_list) { KEY *not_used_1; uint not_used_2; From d89cdfc2291560c1cd9bc55658584577d0ce5ef6 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 13 Feb 2019 18:08:47 +0100 Subject: [PATCH 87/91] bugfix: mysql_fix_privilege_tables table_schema=database() fix mysql_fix_privilege_tables to look for the `user` table in the correct schema when deciding whether to convert it to `global_priv` table make related tests a bit more verbose --- .../main/system_mysql_db_fix40123.result | 76 ++++++---------- mysql-test/main/system_mysql_db_fix40123.test | 55 ++++-------- .../main/system_mysql_db_fix50030.result | 80 +++++++---------- mysql-test/main/system_mysql_db_fix50030.test | 62 +++++-------- .../main/system_mysql_db_fix50117.result | 76 ++++++---------- mysql-test/main/system_mysql_db_fix50117.test | 87 +++++-------------- scripts/mysql_system_tables_fix.sql | 2 +- 7 files changed, 139 insertions(+), 299 deletions(-) diff --git a/mysql-test/main/system_mysql_db_fix40123.result b/mysql-test/main/system_mysql_db_fix40123.result index c4c4d3df706..6ec1e35b0b7 100644 --- a/mysql-test/main/system_mysql_db_fix40123.result +++ b/mysql-test/main/system_mysql_db_fix40123.result @@ -1,3 +1,24 @@ +use test; +set storage_engine=myisam; +CREATE TABLE db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; +INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); +INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); +CREATE TABLE host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; +CREATE TABLE user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; +INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); +INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); +CREATE TABLE func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; +CREATE TABLE tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; +CREATE TABLE columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; +CREATE TABLE help_topic ( help_topic_id int unsigned not null, name varchar(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url varchar(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics'; +CREATE TABLE help_category ( help_category_id smallint unsigned not null, name varchar(64) not null, parent_category_id smallint unsigned null, url varchar(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories'; +CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; +CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name varchar(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; +CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; +CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; +CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; +CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; +CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; show tables; Tables_in_db column_stats @@ -62,57 +83,8 @@ db CREATE TABLE `db` ( KEY `User` (`User`) ) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Database privileges' show create table user; -Table Create Table -user CREATE TABLE `user` ( - `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', - `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', - `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', - `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', - `ssl_cipher` blob NOT NULL, - `x509_issuer` blob NOT NULL, - `x509_subject` blob NOT NULL, - `max_questions` int(11) unsigned NOT NULL DEFAULT 0, - `max_updates` int(11) unsigned NOT NULL DEFAULT 0, - `max_connections` int(11) unsigned NOT NULL DEFAULT 0, - `max_user_connections` int(11) NOT NULL DEFAULT 0, - `plugin` char(64) CHARACTER SET latin1 NOT NULL DEFAULT '', - `authentication_string` text COLLATE utf8_bin NOT NULL, - `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', - `max_statement_time` decimal(12,6) NOT NULL DEFAULT 0.000000, - PRIMARY KEY (`Host`,`User`) -) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' +View Create View character_set_client collation_connection +user CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `user` AS select `global_priv`.`Host` AS `Host`,`global_priv`.`User` AS `User`,if(json_value(`global_priv`.`Priv`,'$.plugin') in ('mysql_native_password','mysql_old_password'),ifnull(json_value(`global_priv`.`Priv`,'$.authentication_string'),''),'') AS `Password`,if(json_value(`global_priv`.`Priv`,'$.access') & 1,'Y','N') AS `Select_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2,'Y','N') AS `Insert_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4,'Y','N') AS `Update_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8,'Y','N') AS `Delete_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16,'Y','N') AS `Create_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 32,'Y','N') AS `Drop_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 64,'Y','N') AS `Reload_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 128,'Y','N') AS `Shutdown_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 256,'Y','N') AS `Process_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 512,'Y','N') AS `File_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 1024,'Y','N') AS `Grant_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2048,'Y','N') AS `References_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4096,'Y','N') AS `Index_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8192,'Y','N') AS `Alter_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16384,'Y','N') AS `Show_db_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 32768,'Y','N') AS `Super_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 65536,'Y','N') AS `Create_tmp_table_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 131072,'Y','N') AS `Lock_tables_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 262144,'Y','N') AS `Execute_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 524288,'Y','N') AS `Repl_slave_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 1048576,'Y','N') AS `Repl_client_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2097152,'Y','N') AS `Create_view_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4194304,'Y','N') AS `Show_view_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8388608,'Y','N') AS `Create_routine_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16777216,'Y','N') AS `Alter_routine_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 33554432,'Y','N') AS `Create_user_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 67108864,'Y','N') AS `Event_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 134217728,'Y','N') AS `Trigger_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 268435456,'Y','N') AS `Create_tablespace_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 536870912,'Y','N') AS `Delete_history_priv`,elt(ifnull(json_value(`global_priv`.`Priv`,'$.ssl_type'),0) + 1,'','ANY','X509','SPECIFIED') AS `ssl_type`,ifnull(json_value(`global_priv`.`Priv`,'$.ssl_cipher'),'') AS `ssl_cipher`,ifnull(json_value(`global_priv`.`Priv`,'$.x509_issuer'),'') AS `x509_issuer`,ifnull(json_value(`global_priv`.`Priv`,'$.x509_subject'),'') AS `x509_subject`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_questions'),0) as unsigned) AS `max_questions`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_updates'),0) as unsigned) AS `max_updates`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_connections'),0) as unsigned) AS `max_connections`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_user_connections'),0) as signed) AS `max_user_connections`,ifnull(json_value(`global_priv`.`Priv`,'$.plugin'),'') AS `plugin`,ifnull(json_value(`global_priv`.`Priv`,'$.authentication_string'),'') AS `authentication_string`,'N' AS `password_expired`,elt(ifnull(json_value(`global_priv`.`Priv`,'$.is_role'),0) + 1,'N','Y') AS `is_role`,ifnull(json_value(`global_priv`.`Priv`,'$.default_role'),'') AS `default_role`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_statement_time'),0.0) as decimal(12,6)) AS `max_statement_time` from `global_priv` latin1 latin1_swedish_ci show create table func; Table Create Table func CREATE TABLE `func` ( @@ -298,5 +270,7 @@ index_stats CREATE TABLE `index_stats` ( `avg_frequency` decimal(12,4) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) ) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes' +DROP VIEW user; +DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; show tables; Tables_in_test diff --git a/mysql-test/main/system_mysql_db_fix40123.test b/mysql-test/main/system_mysql_db_fix40123.test index 3f313c4ec1f..00747cd7ba0 100644 --- a/mysql-test/main/system_mysql_db_fix40123.test +++ b/mysql-test/main/system_mysql_db_fix40123.test @@ -19,62 +19,43 @@ if (!$MYSQL_FIX_PRIVILEGE_TABLES) # mysql_fix_system_tables which should be ignored. # Instead, concentrate on the errors in r/system_mysql_db.reject --- disable_result_log --- disable_query_log - use test; # create system tables as in mysql-4.1.23 # created by executing "./mysql_create_system_tables real ." set storage_engine=myisam; -CREATE TABLE db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; +CREATE TABLE db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y'); - -CREATE TABLE host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; - - -CREATE TABLE user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; +CREATE TABLE host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; +CREATE TABLE user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0); - -CREATE TABLE func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; - - -CREATE TABLE tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; -CREATE TABLE columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; - -CREATE TABLE help_topic ( help_topic_id int unsigned not null, name varchar(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url varchar(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics'; -CREATE TABLE help_category ( help_category_id smallint unsigned not null, name varchar(64) not null, parent_category_id smallint unsigned null, url varchar(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories'; -CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; -CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name varchar(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; - -CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; - -CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; - -CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; - -CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; - -CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; +CREATE TABLE func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; +CREATE TABLE tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; +CREATE TABLE columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; +CREATE TABLE help_topic ( help_topic_id int unsigned not null, name varchar(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url varchar(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics'; +CREATE TABLE help_category ( help_category_id smallint unsigned not null, name varchar(64) not null, parent_category_id smallint unsigned null, url varchar(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories'; +CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; +CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name varchar(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; +CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; +CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; +CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; +CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; +CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; # Run the mysql_fix_privilege_tables.sql using "mysql --force" +-- disable_result_log --exec $MYSQL --force test < $MYSQL_FIX_PRIVILEGE_TABLES - --- enable_query_log -- enable_result_log # Dump the tables that should be compared -- source include/system_db_struct.inc --- disable_query_log - # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; - --- enable_query_log +DROP VIEW user; +DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; # check that we dropped all system tables show tables; diff --git a/mysql-test/main/system_mysql_db_fix50030.result b/mysql-test/main/system_mysql_db_fix50030.result index 3a79afb04f0..9f2729b86d1 100644 --- a/mysql-test/main/system_mysql_db_fix50030.result +++ b/mysql-test/main/system_mysql_db_fix50030.result @@ -1,3 +1,28 @@ +use test; +set storage_engine=myisam; +CREATE TABLE db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; +INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N'); +INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N'); +CREATE TABLE host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; +CREATE TABLE user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; +INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); +INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0, 0); +CREATE TABLE func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; +CREATE TABLE tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; +CREATE TABLE columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; +CREATE TABLE help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url char(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics'; +CREATE TABLE help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url char(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories'; +CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; +CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; +CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; +CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; +CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; +CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; +CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; +CREATE TABLE proc ( db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob DEFAULT '' NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob DEFAULT '' NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, PRIMARY KEY (db,name,type) ) engine=MyISAM character set utf8 comment='Stored Procedures'; +CREATE TABLE procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; +CREATE TABLE servers ( Server_name char(64) NOT NULL DEFAULT '', Host char(64) NOT NULL DEFAULT '', Db char(64) NOT NULL DEFAULT '', Username char(64) NOT NULL DEFAULT '', Password char(64) NOT NULL DEFAULT '', Port INT(4) NOT NULL DEFAULT '0', Socket char(64) NOT NULL DEFAULT '', Wrapper char(64) NOT NULL DEFAULT '', Owner char(64) NOT NULL DEFAULT '', PRIMARY KEY (Server_name)) CHARACTER SET utf8 comment='MySQL Foreign Servers table'; +INSERT INTO servers VALUES ('test','localhost','test','root','', 0,'','mysql','root'); show tables; Tables_in_db column_stats @@ -62,57 +87,8 @@ db CREATE TABLE `db` ( KEY `User` (`User`) ) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Database privileges' show create table user; -Table Create Table -user CREATE TABLE `user` ( - `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', - `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', - `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', - `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', - `ssl_cipher` blob NOT NULL, - `x509_issuer` blob NOT NULL, - `x509_subject` blob NOT NULL, - `max_questions` int(11) unsigned NOT NULL DEFAULT 0, - `max_updates` int(11) unsigned NOT NULL DEFAULT 0, - `max_connections` int(11) unsigned NOT NULL DEFAULT 0, - `max_user_connections` int(11) NOT NULL DEFAULT 0, - `plugin` char(64) CHARACTER SET latin1 NOT NULL DEFAULT '', - `authentication_string` text COLLATE utf8_bin NOT NULL, - `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', - `max_statement_time` decimal(12,6) NOT NULL DEFAULT 0.000000, - PRIMARY KEY (`Host`,`User`) -) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' +View Create View character_set_client collation_connection +user CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `user` AS select `global_priv`.`Host` AS `Host`,`global_priv`.`User` AS `User`,if(json_value(`global_priv`.`Priv`,'$.plugin') in ('mysql_native_password','mysql_old_password'),ifnull(json_value(`global_priv`.`Priv`,'$.authentication_string'),''),'') AS `Password`,if(json_value(`global_priv`.`Priv`,'$.access') & 1,'Y','N') AS `Select_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2,'Y','N') AS `Insert_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4,'Y','N') AS `Update_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8,'Y','N') AS `Delete_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16,'Y','N') AS `Create_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 32,'Y','N') AS `Drop_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 64,'Y','N') AS `Reload_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 128,'Y','N') AS `Shutdown_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 256,'Y','N') AS `Process_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 512,'Y','N') AS `File_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 1024,'Y','N') AS `Grant_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2048,'Y','N') AS `References_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4096,'Y','N') AS `Index_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8192,'Y','N') AS `Alter_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16384,'Y','N') AS `Show_db_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 32768,'Y','N') AS `Super_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 65536,'Y','N') AS `Create_tmp_table_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 131072,'Y','N') AS `Lock_tables_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 262144,'Y','N') AS `Execute_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 524288,'Y','N') AS `Repl_slave_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 1048576,'Y','N') AS `Repl_client_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2097152,'Y','N') AS `Create_view_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4194304,'Y','N') AS `Show_view_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8388608,'Y','N') AS `Create_routine_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16777216,'Y','N') AS `Alter_routine_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 33554432,'Y','N') AS `Create_user_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 67108864,'Y','N') AS `Event_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 134217728,'Y','N') AS `Trigger_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 268435456,'Y','N') AS `Create_tablespace_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 536870912,'Y','N') AS `Delete_history_priv`,elt(ifnull(json_value(`global_priv`.`Priv`,'$.ssl_type'),0) + 1,'','ANY','X509','SPECIFIED') AS `ssl_type`,ifnull(json_value(`global_priv`.`Priv`,'$.ssl_cipher'),'') AS `ssl_cipher`,ifnull(json_value(`global_priv`.`Priv`,'$.x509_issuer'),'') AS `x509_issuer`,ifnull(json_value(`global_priv`.`Priv`,'$.x509_subject'),'') AS `x509_subject`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_questions'),0) as unsigned) AS `max_questions`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_updates'),0) as unsigned) AS `max_updates`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_connections'),0) as unsigned) AS `max_connections`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_user_connections'),0) as signed) AS `max_user_connections`,ifnull(json_value(`global_priv`.`Priv`,'$.plugin'),'') AS `plugin`,ifnull(json_value(`global_priv`.`Priv`,'$.authentication_string'),'') AS `authentication_string`,'N' AS `password_expired`,elt(ifnull(json_value(`global_priv`.`Priv`,'$.is_role'),0) + 1,'N','Y') AS `is_role`,ifnull(json_value(`global_priv`.`Priv`,'$.default_role'),'') AS `default_role`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_statement_time'),0.0) as decimal(12,6)) AS `max_statement_time` from `global_priv` latin1 latin1_swedish_ci show create table func; Table Create Table func CREATE TABLE `func` ( @@ -298,5 +274,7 @@ index_stats CREATE TABLE `index_stats` ( `avg_frequency` decimal(12,4) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) ) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes' +DROP VIEW user; +DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; show tables; Tables_in_test diff --git a/mysql-test/main/system_mysql_db_fix50030.test b/mysql-test/main/system_mysql_db_fix50030.test index 33dcc873615..085286637b0 100644 --- a/mysql-test/main/system_mysql_db_fix50030.test +++ b/mysql-test/main/system_mysql_db_fix50030.test @@ -19,69 +19,47 @@ if (!$MYSQL_FIX_PRIVILEGE_TABLES) # mysql_fix_system_tables which should be ignored. # Instead, concentrate on the errors in r/system_mysql_db.reject --- disable_result_log --- disable_query_log - use test; # create system tables as in mysql-5.0.30 # created by executing "./mysql_create_system_tables real ." set storage_engine=myisam; -CREATE TABLE db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; +CREATE TABLE db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N'); INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N'); - -CREATE TABLE host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; - -CREATE TABLE user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; +CREATE TABLE host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; +CREATE TABLE user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0); INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0, 0); - -CREATE TABLE func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; - -CREATE TABLE tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; - -CREATE TABLE columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; - -CREATE TABLE help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url char(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics'; -CREATE TABLE help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url char(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories'; -CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; -CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; - -CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; - -CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; - -CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; - -CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; - -CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; - -CREATE TABLE proc ( db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob DEFAULT '' NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob DEFAULT '' NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, PRIMARY KEY (db,name,type) ) engine=MyISAM character set utf8 comment='Stored Procedures'; - -CREATE TABLE procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; - +CREATE TABLE func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; +CREATE TABLE tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; +CREATE TABLE columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; +CREATE TABLE help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url char(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics'; +CREATE TABLE help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url char(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories'; +CREATE TABLE help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; +CREATE TABLE help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; +CREATE TABLE time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; +CREATE TABLE time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; +CREATE TABLE time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; +CREATE TABLE time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; +CREATE TABLE time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; +CREATE TABLE proc ( db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob DEFAULT '' NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob DEFAULT '' NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, PRIMARY KEY (db,name,type) ) engine=MyISAM character set utf8 comment='Stored Procedures'; +CREATE TABLE procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; CREATE TABLE servers ( Server_name char(64) NOT NULL DEFAULT '', Host char(64) NOT NULL DEFAULT '', Db char(64) NOT NULL DEFAULT '', Username char(64) NOT NULL DEFAULT '', Password char(64) NOT NULL DEFAULT '', Port INT(4) NOT NULL DEFAULT '0', Socket char(64) NOT NULL DEFAULT '', Wrapper char(64) NOT NULL DEFAULT '', Owner char(64) NOT NULL DEFAULT '', PRIMARY KEY (Server_name)) CHARACTER SET utf8 comment='MySQL Foreign Servers table'; - INSERT INTO servers VALUES ('test','localhost','test','root','', 0,'','mysql','root'); +-- disable_result_log # Run the mysql_fix_privilege_tables.sql using "mysql --force" --exec $MYSQL --force test < $MYSQL_FIX_PRIVILEGE_TABLES - --- enable_query_log -- enable_result_log # Dump the tables that should be compared -- source include/system_db_struct.inc --- disable_query_log - # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; - --- enable_query_log +DROP VIEW user; +DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; # check that we dropped all system tables show tables; diff --git a/mysql-test/main/system_mysql_db_fix50117.result b/mysql-test/main/system_mysql_db_fix50117.result index c4c4d3df706..08f334e9bcc 100644 --- a/mysql-test/main/system_mysql_db_fix50117.result +++ b/mysql-test/main/system_mysql_db_fix50117.result @@ -1,3 +1,24 @@ +use test; +CREATE TABLE IF NOT EXISTS db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; +CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; +CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; +CREATE TABLE IF NOT EXISTS func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; +CREATE TABLE IF NOT EXISTS plugin ( name char(64) binary DEFAULT '' NOT NULL, dl char(128) DEFAULT '' NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='MySQL plugins'; +CREATE TABLE IF NOT EXISTS servers ( Server_name char(64) NOT NULL DEFAULT '', Host char(64) NOT NULL DEFAULT '', Db char(64) NOT NULL DEFAULT '', Username char(64) NOT NULL DEFAULT '', Password char(64) NOT NULL DEFAULT '', Port INT(4) NOT NULL DEFAULT '0', Socket char(64) NOT NULL DEFAULT '', Wrapper char(64) NOT NULL DEFAULT '', Owner char(64) NOT NULL DEFAULT '', PRIMARY KEY (Server_name)) CHARACTER SET utf8 comment='MySQL Foreign Servers table'; +CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; +CREATE TABLE IF NOT EXISTS columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; +CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url char(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics'; +CREATE TABLE IF NOT EXISTS help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url char(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories'; +CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; +CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; +CREATE TABLE IF NOT EXISTS time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; +CREATE TABLE IF NOT EXISTS time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; +CREATE TABLE IF NOT EXISTS time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; +CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; +CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; +CREATE TABLE IF NOT EXISTS proc ( db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, PRIMARY KEY (db,name,type) ) engine=MyISAM character set utf8 comment='Stored Procedures'; +CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; +CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events'; show tables; Tables_in_db column_stats @@ -62,57 +83,8 @@ db CREATE TABLE `db` ( KEY `User` (`User`) ) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Database privileges' show create table user; -Table Create Table -user CREATE TABLE `user` ( - `Host` char(60) COLLATE utf8_bin NOT NULL DEFAULT '', - `User` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', - `Password` char(41) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', - `Select_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Insert_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Update_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Drop_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Reload_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Shutdown_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Process_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `File_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Grant_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `References_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Index_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_db_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Super_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tmp_table_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Lock_tables_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Execute_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Repl_slave_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Repl_client_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Show_view_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Alter_routine_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_user_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Event_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Trigger_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Create_tablespace_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `Delete_history_priv` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `ssl_type` enum('','ANY','X509','SPECIFIED') CHARACTER SET utf8 NOT NULL DEFAULT '', - `ssl_cipher` blob NOT NULL, - `x509_issuer` blob NOT NULL, - `x509_subject` blob NOT NULL, - `max_questions` int(11) unsigned NOT NULL DEFAULT 0, - `max_updates` int(11) unsigned NOT NULL DEFAULT 0, - `max_connections` int(11) unsigned NOT NULL DEFAULT 0, - `max_user_connections` int(11) NOT NULL DEFAULT 0, - `plugin` char(64) CHARACTER SET latin1 NOT NULL DEFAULT '', - `authentication_string` text COLLATE utf8_bin NOT NULL, - `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', - `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', - `max_statement_time` decimal(12,6) NOT NULL DEFAULT 0.000000, - PRIMARY KEY (`Host`,`User`) -) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=1 COMMENT='Users and global privileges' +View Create View character_set_client collation_connection +user CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `user` AS select `global_priv`.`Host` AS `Host`,`global_priv`.`User` AS `User`,if(json_value(`global_priv`.`Priv`,'$.plugin') in ('mysql_native_password','mysql_old_password'),ifnull(json_value(`global_priv`.`Priv`,'$.authentication_string'),''),'') AS `Password`,if(json_value(`global_priv`.`Priv`,'$.access') & 1,'Y','N') AS `Select_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2,'Y','N') AS `Insert_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4,'Y','N') AS `Update_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8,'Y','N') AS `Delete_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16,'Y','N') AS `Create_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 32,'Y','N') AS `Drop_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 64,'Y','N') AS `Reload_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 128,'Y','N') AS `Shutdown_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 256,'Y','N') AS `Process_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 512,'Y','N') AS `File_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 1024,'Y','N') AS `Grant_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2048,'Y','N') AS `References_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4096,'Y','N') AS `Index_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8192,'Y','N') AS `Alter_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16384,'Y','N') AS `Show_db_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 32768,'Y','N') AS `Super_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 65536,'Y','N') AS `Create_tmp_table_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 131072,'Y','N') AS `Lock_tables_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 262144,'Y','N') AS `Execute_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 524288,'Y','N') AS `Repl_slave_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 1048576,'Y','N') AS `Repl_client_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 2097152,'Y','N') AS `Create_view_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 4194304,'Y','N') AS `Show_view_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 8388608,'Y','N') AS `Create_routine_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 16777216,'Y','N') AS `Alter_routine_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 33554432,'Y','N') AS `Create_user_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 67108864,'Y','N') AS `Event_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 134217728,'Y','N') AS `Trigger_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 268435456,'Y','N') AS `Create_tablespace_priv`,if(json_value(`global_priv`.`Priv`,'$.access') & 536870912,'Y','N') AS `Delete_history_priv`,elt(ifnull(json_value(`global_priv`.`Priv`,'$.ssl_type'),0) + 1,'','ANY','X509','SPECIFIED') AS `ssl_type`,ifnull(json_value(`global_priv`.`Priv`,'$.ssl_cipher'),'') AS `ssl_cipher`,ifnull(json_value(`global_priv`.`Priv`,'$.x509_issuer'),'') AS `x509_issuer`,ifnull(json_value(`global_priv`.`Priv`,'$.x509_subject'),'') AS `x509_subject`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_questions'),0) as unsigned) AS `max_questions`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_updates'),0) as unsigned) AS `max_updates`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_connections'),0) as unsigned) AS `max_connections`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_user_connections'),0) as signed) AS `max_user_connections`,ifnull(json_value(`global_priv`.`Priv`,'$.plugin'),'') AS `plugin`,ifnull(json_value(`global_priv`.`Priv`,'$.authentication_string'),'') AS `authentication_string`,'N' AS `password_expired`,elt(ifnull(json_value(`global_priv`.`Priv`,'$.is_role'),0) + 1,'N','Y') AS `is_role`,ifnull(json_value(`global_priv`.`Priv`,'$.default_role'),'') AS `default_role`,cast(ifnull(json_value(`global_priv`.`Priv`,'$.max_statement_time'),0.0) as decimal(12,6)) AS `max_statement_time` from `global_priv` latin1 latin1_swedish_ci show create table func; Table Create Table func CREATE TABLE `func` ( @@ -298,5 +270,7 @@ index_stats CREATE TABLE `index_stats` ( `avg_frequency` decimal(12,4) DEFAULT NULL, PRIMARY KEY (`db_name`,`table_name`,`index_name`,`prefix_arity`) ) ENGINE=Aria DEFAULT CHARSET=utf8 COLLATE=utf8_bin PAGE_CHECKSUM=1 TRANSACTIONAL=0 COMMENT='Statistics on Indexes' +DROP VIEW user; +DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; show tables; Tables_in_test diff --git a/mysql-test/main/system_mysql_db_fix50117.test b/mysql-test/main/system_mysql_db_fix50117.test index 2fe6869d761..9755415c6e4 100644 --- a/mysql-test/main/system_mysql_db_fix50117.test +++ b/mysql-test/main/system_mysql_db_fix50117.test @@ -19,86 +19,41 @@ if (!$MYSQL_FIX_PRIVILEGE_TABLES) # mysql_fix_system_tables which should be ignored. # Instead, concentrate on the errors in r/system_mysql_db.reject --- disable_result_log --- disable_query_log - use test; # create system tables as in mysql-5.1.17 - - -CREATE TABLE IF NOT EXISTS db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; - - -CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; - - -CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; - - -CREATE TABLE IF NOT EXISTS func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; - - +CREATE TABLE IF NOT EXISTS db ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges'; +CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; +CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; +CREATE TABLE IF NOT EXISTS func ( name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') COLLATE utf8_general_ci NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions'; CREATE TABLE IF NOT EXISTS plugin ( name char(64) binary DEFAULT '' NOT NULL, dl char(128) DEFAULT '' NOT NULL, PRIMARY KEY (name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='MySQL plugins'; - - CREATE TABLE IF NOT EXISTS servers ( Server_name char(64) NOT NULL DEFAULT '', Host char(64) NOT NULL DEFAULT '', Db char(64) NOT NULL DEFAULT '', Username char(64) NOT NULL DEFAULT '', Password char(64) NOT NULL DEFAULT '', Port INT(4) NOT NULL DEFAULT '0', Socket char(64) NOT NULL DEFAULT '', Wrapper char(64) NOT NULL DEFAULT '', Owner char(64) NOT NULL DEFAULT '', PRIMARY KEY (Server_name)) CHARACTER SET utf8 comment='MySQL Foreign Servers table'; +CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; +CREATE TABLE IF NOT EXISTS columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; +CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url char(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics'; +CREATE TABLE IF NOT EXISTS help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url char(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories'; +CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; +CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; +CREATE TABLE IF NOT EXISTS time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; +CREATE TABLE IF NOT EXISTS time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; +CREATE TABLE IF NOT EXISTS time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; +CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; +CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; +CREATE TABLE IF NOT EXISTS proc ( db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, PRIMARY KEY (db,name,type) ) engine=MyISAM character set utf8 comment='Stored Procedures'; +CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; +CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events'; - -CREATE TABLE IF NOT EXISTS tables_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter','Create View','Show view','Trigger') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges'; - -CREATE TABLE IF NOT EXISTS columns_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, Column_priv set('Select','Insert','Update','References') COLLATE utf8_general_ci DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges'; - - -CREATE TABLE IF NOT EXISTS help_topic ( help_topic_id int unsigned not null, name char(64) not null, help_category_id smallint unsigned not null, description text not null, example text not null, url char(128) not null, primary key (help_topic_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help topics'; - - -CREATE TABLE IF NOT EXISTS help_category ( help_category_id smallint unsigned not null, name char(64) not null, parent_category_id smallint unsigned null, url char(128) not null, primary key (help_category_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help categories'; - - -CREATE TABLE IF NOT EXISTS help_relation ( help_topic_id int unsigned not null references help_topic, help_keyword_id int unsigned not null references help_keyword, primary key (help_keyword_id, help_topic_id) ) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation'; - - -CREATE TABLE IF NOT EXISTS help_keyword ( help_keyword_id int unsigned not null, name char(64) not null, primary key (help_keyword_id), unique index (name) ) engine=MyISAM CHARACTER SET utf8 comment='help keywords'; - - -CREATE TABLE IF NOT EXISTS time_zone_name ( Name char(64) NOT NULL, Time_zone_id int unsigned NOT NULL, PRIMARY KEY Name (Name) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone names'; - - -CREATE TABLE IF NOT EXISTS time_zone ( Time_zone_id int unsigned NOT NULL auto_increment, Use_leap_seconds enum('Y','N') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY TzId (Time_zone_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zones'; - - -CREATE TABLE IF NOT EXISTS time_zone_transition ( Time_zone_id int unsigned NOT NULL, Transition_time bigint signed NOT NULL, Transition_type_id int unsigned NOT NULL, PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions'; - - -CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsigned NOT NULL, Transition_type_id int unsigned NOT NULL, Offset int signed DEFAULT 0 NOT NULL, Is_DST tinyint unsigned DEFAULT 0 NOT NULL, Abbreviation char(8) DEFAULT '' NOT NULL, PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id) ) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types'; - - -CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; - - -CREATE TABLE IF NOT EXISTS proc ( db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum('CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, PRIMARY KEY (db,name,type) ) engine=MyISAM character set utf8 comment='Stored Procedures'; - - -CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; - -CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', name char(64) CHARACTER SET utf8 NOT NULL default '', body longblob NOT NULL, definer char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', execute_at DATETIME default NULL, interval_value int(11) default NULL, interval_field ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00', last_executed DATETIME default NULL, starts DATETIME default NULL, ends DATETIME default NULL, status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED', on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP', sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', time_zone char(64) CHARACTER SET latin1 NOT NULL DEFAULT 'SYSTEM', PRIMARY KEY (db, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events'; - +-- disable_result_log # Run the mysql_fix_privilege_tables.sql using "mysql --force" --exec $MYSQL --force test < $MYSQL_FIX_PRIVILEGE_TABLES - --- enable_query_log -- enable_result_log # Dump the tables that should be compared -- source include/system_db_struct.inc --- disable_query_log - # Drop all tables created by this test -DROP TABLE db, host, user, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; - --- enable_query_log +DROP VIEW user; +DROP TABLE db, host, func, plugin, tables_priv, columns_priv, procs_priv, servers, help_category, help_keyword, help_relation, help_topic, proc, time_zone, time_zone_leap_second, time_zone_name, time_zone_transition, time_zone_transition_type, general_log, slow_log, event, proxies_priv, innodb_index_stats, innodb_table_stats, transaction_registry, table_stats, column_stats, index_stats, roles_mapping, gtid_slave_pos, global_priv; # check that we dropped all system tables show tables; diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index e80569d6636..fe0b9c01600 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -760,7 +760,7 @@ ALTER TABLE column_stats ENGINE=Aria transactional=0; ALTER TABLE index_stats ENGINE=Aria transactional=0; DELIMITER // -IF 'BASE TABLE' = (select table_type from information_schema.tables where table_name='user') THEN +IF 'BASE TABLE' = (select table_type from information_schema.tables where table_schema=database() and table_name='user') THEN CREATE TABLE IF NOT EXISTS global_priv (Host char(60) binary DEFAULT '', User char(80) binary DEFAULT '', Priv JSON NOT NULL DEFAULT '{}' CHECK(JSON_VALID(Priv)), PRIMARY KEY Host (Host,User)) engine=Aria transactional=1 CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges' SELECT Host, User, JSON_COMPACT(JSON_OBJECT('access', 1*('Y'=Select_priv)+ From 6c8ce999f861c8c56edaf6b6e965c6c48bd9e37c Mon Sep 17 00:00:00 2001 From: Robert Bindar Date: Wed, 13 Feb 2019 20:02:42 +0100 Subject: [PATCH 88/91] MDEV-13095 Implement User Account locking Add server support for user account locking. This patch extends the ALTER/CREATE USER statements for denying a user's subsequent login attempts: ALTER USER user [, user2] ACCOUNT [LOCK | UNLOCK] CREATE USER user [, user2] ACCOUNT [LOCK | UNLOCK] The SHOW CREATE USER statement was updated to display the locking state of an user. Closes #1006 --- mysql-test/main/lock_user.result | 134 +++++++++++++++++++ mysql-test/main/lock_user.test | 142 +++++++++++++++++++++ mysql-test/main/system_mysql_db_507.result | 21 +++ mysql-test/main/system_mysql_db_507.test | 18 +++ scripts/mysql_system_tables_fix.sql | 2 + sql/lex.h | 1 + sql/share/errmsg-utf8.txt | 3 + sql/sql_acl.cc | 42 +++++- sql/sql_lex.h | 24 ++++ sql/sql_yacc.yy | 19 ++- sql/sql_yacc_ora.yy | 18 ++- 11 files changed, 419 insertions(+), 5 deletions(-) create mode 100644 mysql-test/main/lock_user.result create mode 100644 mysql-test/main/lock_user.test diff --git a/mysql-test/main/lock_user.result b/mysql-test/main/lock_user.result new file mode 100644 index 00000000000..a8740e8ad37 --- /dev/null +++ b/mysql-test/main/lock_user.result @@ -0,0 +1,134 @@ +create user user1@localhost; +create user user2@localhost; +# +# Only privileged users should be able to lock/unlock. +# +alter user user1@localhost account lock; +alter user user1@localhost account unlock; +create user user3@localhost account lock; +drop user user3@localhost; +connect con1,localhost,user1; +connection con1; +alter user user2@localhost account lock; +ERROR 42000: Access denied; you need (at least one of) the CREATE USER privilege(s) for this operation +disconnect con1; +connection default; +# +# ALTER USER USER1 ACCOUNT LOCK should deny the connection of user1, +# but it should allow user2 to connect. +# +alter user user1@localhost account lock; +connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK); +connect con1,localhost,user1; +ERROR HY000: Access denied, this account is locked +connect con2,localhost,user2; +disconnect con2; +connection default; +alter user user1@localhost account unlock; +# +# Passing an incorrect user should return an error unless +# IF EXISTS is used +# +alter user inexistentUser@localhost account lock; +ERROR HY000: Operation ALTER USER failed for 'inexistentUser'@'localhost' +alter if exists user inexistentUser@localhost account lock; +Warnings: +Error 1133 Can't find any matching row in the user table +Note 1396 Operation ALTER USER failed for 'inexistentUser'@'localhost' +# +# Passing an existing user to CREATE should not be allowed +# and it should not change the locking state of the current user +# +show create user user1@localhost; +CREATE USER for user1@localhost +CREATE USER 'user1'@'localhost' +create user user1@localhost account lock; +ERROR HY000: Operation CREATE USER failed for 'user1'@'localhost' +show create user user1@localhost; +CREATE USER for user1@localhost +CREATE USER 'user1'@'localhost' +# +# Passing multiple users should lock them all +# +alter user user1@localhost, user2@localhost account lock; +connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK); +connect con1,localhost,user1; +ERROR HY000: Access denied, this account is locked +connect(localhost,user2,,test,MYSQL_PORT,MYSQL_SOCK); +connect con2,localhost,user2; +ERROR HY000: Access denied, this account is locked +alter user user1@localhost, user2@localhost account unlock; +# +# The locking state is preserved after acl reload +# +alter user user1@localhost account lock; +flush privileges; +connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK); +connect con1,localhost,user1; +ERROR HY000: Access denied, this account is locked +alter user user1@localhost account unlock; +# +# JSON functions on global_priv reflect the locking state of an account +# +alter user user1@localhost account lock; +select host, user, JSON_VALUE(Priv, '$.account_locked') from mysql.global_priv where user='user1'; +host user JSON_VALUE(Priv, '$.account_locked') +localhost user1 1 +alter user user1@localhost account unlock; +select host, user, JSON_VALUE(Priv, '$.account_locked') from mysql.global_priv where user='user1'; +host user JSON_VALUE(Priv, '$.account_locked') +localhost user1 0 +# +# SHOW CREATE USER correctly displays the locking state of an user +# +show create user user1@localhost; +CREATE USER for user1@localhost +CREATE USER 'user1'@'localhost' +alter user user1@localhost account lock; +show create user user1@localhost; +CREATE USER for user1@localhost +CREATE USER 'user1'@'localhost' ACCOUNT LOCK +alter user user1@localhost account unlock; +show create user user1@localhost; +CREATE USER for user1@localhost +CREATE USER 'user1'@'localhost' +create user newuser@localhost account lock; +show create user newuser@localhost; +CREATE USER for newuser@localhost +CREATE USER 'newuser'@'localhost' ACCOUNT LOCK +drop user newuser@localhost; +# +# Users should be able to lock themselves +# +grant CREATE USER on *.* to user1@localhost; +connect con1,localhost,user1; +connection con1; +alter user user1@localhost account lock; +disconnect con1; +connection default; +connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK); +connect con1,localhost,user1; +ERROR HY000: Access denied, this account is locked +alter user user1@localhost account unlock; +# +# Users should be able to unlock themselves if the connections +# had been established before the accounts were locked +# +grant CREATE USER on *.* to user1@localhost; +connect con1,localhost,user1; +alter user user1@localhost account lock; +connection con1; +alter user user1@localhost account unlock; +show create user user1@localhost; +CREATE USER for user1@localhost +CREATE USER 'user1'@'localhost' +disconnect con1; +connection default; +# +# COM_CHANGE_USER should return error if the destination +# account is locked +# +alter user user1@localhost account lock; +ERROR HY000: Access denied, this account is locked +drop user user1@localhost; +drop user user2@localhost; diff --git a/mysql-test/main/lock_user.test b/mysql-test/main/lock_user.test new file mode 100644 index 00000000000..366c34ecea8 --- /dev/null +++ b/mysql-test/main/lock_user.test @@ -0,0 +1,142 @@ +# +# Test user account locking +# + +--source include/not_embedded.inc + +create user user1@localhost; +create user user2@localhost; + +--echo # +--echo # Only privileged users should be able to lock/unlock. +--echo # +alter user user1@localhost account lock; +alter user user1@localhost account unlock; +create user user3@localhost account lock; +drop user user3@localhost; + +connect(con1,localhost,user1); +connection con1; +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +alter user user2@localhost account lock; +disconnect con1; +connection default; + +--echo # +--echo # ALTER USER USER1 ACCOUNT LOCK should deny the connection of user1, +--echo # but it should allow user2 to connect. +--echo # + +alter user user1@localhost account lock; +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK +--error ER_ACCOUNT_HAS_BEEN_LOCKED +connect(con1,localhost,user1); +connect(con2,localhost,user2); +disconnect con2; +connection default; +alter user user1@localhost account unlock; + +--echo # +--echo # Passing an incorrect user should return an error unless +--echo # IF EXISTS is used +--echo # + +--error ER_CANNOT_USER +alter user inexistentUser@localhost account lock; + +alter if exists user inexistentUser@localhost account lock; + +--echo # +--echo # Passing an existing user to CREATE should not be allowed +--echo # and it should not change the locking state of the current user +--echo # + +show create user user1@localhost; +--error ER_CANNOT_USER +create user user1@localhost account lock; +show create user user1@localhost; + +--echo # +--echo # Passing multiple users should lock them all +--echo # + +alter user user1@localhost, user2@localhost account lock; +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK +--error ER_ACCOUNT_HAS_BEEN_LOCKED +connect(con1,localhost,user1); +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK +--error ER_ACCOUNT_HAS_BEEN_LOCKED +connect(con2,localhost,user2); +alter user user1@localhost, user2@localhost account unlock; + +--echo # +--echo # The locking state is preserved after acl reload +--echo # + +alter user user1@localhost account lock; +flush privileges; +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK +--error ER_ACCOUNT_HAS_BEEN_LOCKED +connect(con1,localhost,user1); +alter user user1@localhost account unlock; + +--echo # +--echo # JSON functions on global_priv reflect the locking state of an account +--echo # + +alter user user1@localhost account lock; +select host, user, JSON_VALUE(Priv, '$.account_locked') from mysql.global_priv where user='user1'; +alter user user1@localhost account unlock; +select host, user, JSON_VALUE(Priv, '$.account_locked') from mysql.global_priv where user='user1'; + +--echo # +--echo # SHOW CREATE USER correctly displays the locking state of an user +--echo # + +show create user user1@localhost; +alter user user1@localhost account lock; +show create user user1@localhost; +alter user user1@localhost account unlock; +show create user user1@localhost; +create user newuser@localhost account lock; +show create user newuser@localhost; +drop user newuser@localhost; + +--echo # +--echo # Users should be able to lock themselves +--echo # +grant CREATE USER on *.* to user1@localhost; +connect(con1,localhost,user1); +connection con1; +alter user user1@localhost account lock; +disconnect con1; +connection default; +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK +--error ER_ACCOUNT_HAS_BEEN_LOCKED +connect(con1,localhost,user1); +alter user user1@localhost account unlock; + +--echo # +--echo # Users should be able to unlock themselves if the connections +--echo # had been established before the accounts were locked +--echo # +grant CREATE USER on *.* to user1@localhost; +connect(con1,localhost,user1); +alter user user1@localhost account lock; +connection con1; +alter user user1@localhost account unlock; +show create user user1@localhost; +disconnect con1; +connection default; + +--echo # +--echo # COM_CHANGE_USER should return error if the destination +--echo # account is locked +--echo # +alter user user1@localhost account lock; +--error ER_ACCOUNT_HAS_BEEN_LOCKED +--change_user user1 + +drop user user1@localhost; +drop user user2@localhost; + diff --git a/mysql-test/main/system_mysql_db_507.result b/mysql-test/main/system_mysql_db_507.result index 1fa4af66719..bf4d3115da5 100644 --- a/mysql-test/main/system_mysql_db_507.result +++ b/mysql-test/main/system_mysql_db_507.result @@ -165,5 +165,26 @@ foo % Y mysql_native_password *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB goo % Y mysql_native_password *F3A2A51A9B0F2BE2468926B4132313728C250DBF ioo % Y mysql_old_password 7a8f886d28473e85 # +# Test account locking +# +create user user1@localhost account lock; +connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK); +connect con1,localhost,user1; +ERROR HY000: Access denied, this account is locked +flush privileges; +connect(localhost,user1,,test,MYSQL_PORT,MYSQL_SOCK); +connect con1,localhost,user1; +ERROR HY000: Access denied, this account is locked +show create user user1@localhost; +CREATE USER for user1@localhost +CREATE USER 'user1'@'localhost' ACCOUNT LOCK +alter user user1@localhost account unlock; +connect con1,localhost,user1; +disconnect con1; +connection default; +show create user user1@localhost; +CREATE USER for user1@localhost +CREATE USER 'user1'@'localhost' +# # Reset to final original state. # diff --git a/mysql-test/main/system_mysql_db_507.test b/mysql-test/main/system_mysql_db_507.test index b57a2a09c8e..bb8163f6ebe 100644 --- a/mysql-test/main/system_mysql_db_507.test +++ b/mysql-test/main/system_mysql_db_507.test @@ -88,6 +88,24 @@ select user, host, select_priv, plugin, authentication_string from mysql.user where user like "%oo" order by user; +--echo # +--echo # Test account locking +--echo # +create user user1@localhost account lock; +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK +--error ER_ACCOUNT_HAS_BEEN_LOCKED +connect(con1,localhost,user1); +flush privileges; +--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK +--error ER_ACCOUNT_HAS_BEEN_LOCKED +connect(con1,localhost,user1); +show create user user1@localhost; +alter user user1@localhost account unlock; +connect(con1,localhost,user1); +disconnect con1; +connection default; +show create user user1@localhost; + --echo # --echo # Reset to final original state. --echo # diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index fe0b9c01600..381f5356575 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -643,6 +643,7 @@ ALTER TABLE user ADD plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, ALTER TABLE user MODIFY plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, MODIFY authentication_string TEXT NOT NULL; ALTER TABLE user ADD password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; +ALTER TABLE user ADD account_locked enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL after password_expired; ALTER TABLE user ADD is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; ALTER TABLE user ADD default_role char(80) binary DEFAULT '' NOT NULL; ALTER TABLE user ADD max_statement_time decimal(12,6) DEFAULT 0 NOT NULL; @@ -804,6 +805,7 @@ IF 'BASE TABLE' = (select table_type from information_schema.tables where table_ 'max_statement_time', max_statement_time, 'plugin', if(plugin>'',plugin,if(length(password)=16,'mysql_old_password','mysql_native_password')), 'authentication_string', if(plugin>'' and authentication_string>'',authentication_string,password), + 'account_locked', 'Y'=account_locked, 'default_role', default_role, 'is_role', 'Y'=is_role)) as Priv FROM user; diff --git a/sql/lex.h b/sql/lex.h index 5ffe07fa415..bcb085279b3 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -55,6 +55,7 @@ static SYMBOL symbols[] = { { ">>", SYM(SHIFT_RIGHT)}, { "<=>", SYM(EQUAL_SYM)}, { "ACCESSIBLE", SYM(ACCESSIBLE_SYM)}, + { "ACCOUNT", SYM(ACCOUNT_SYM)}, { "ACTION", SYM(ACTION)}, { "ADD", SYM(ADD)}, { "ADMIN", SYM(ADMIN_SYM)}, diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index e09afebe074..f80ae99ac50 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7933,3 +7933,6 @@ ER_BACKUP_UNKNOWN_STAGE eng "Unknown backup stage: '%s'. Stage should be one of START, FLUSH, BLOCK_DDL, BLOCK_COMMIT or END" ER_USER_IS_BLOCKED eng "User is blocked because of too many credential errors; unblock with 'FLUSH PRIVILEGES'" +ER_ACCOUNT_HAS_BEEN_LOCKED + eng "Access denied, this account is locked" + rum "Acces refuzat, acest cont este blocat" diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ad9e2b446ed..9b457963a5e 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -152,6 +152,7 @@ public: LEX_CSTRING default_rolename; struct AUTH { LEX_CSTRING plugin, auth_string, salt; } *auth; uint nauth; + bool account_locked; bool alloc_auth(MEM_ROOT *root, uint n) { @@ -864,6 +865,8 @@ class User_table: public Grant_table_base virtual int set_is_role (bool x) const = 0; virtual const char* get_default_role (MEM_ROOT *root) const = 0; virtual int set_default_role (const char *s, size_t l) const = 0; + virtual bool get_account_locked () const = 0; + virtual int set_account_locked (bool x) const = 0; virtual ~User_table() {} private: @@ -1123,7 +1126,22 @@ class User_table_tabular: public User_table return f->store(s, l, system_charset_info); else return 1; - }; + } + /* On a MariaDB 10.3 user table, the account locking accessors will try to + get the content of the max_statement_time column, but they will fail due + to the typecheck in get_field. */ + bool get_account_locked () const + { + Field *f= get_field(end_priv_columns + 13, MYSQL_TYPE_ENUM); + return f ? f->val_int()-1 : 0; + } + int set_account_locked (bool x) const + { + if (Field *f= get_field(end_priv_columns + 13, MYSQL_TYPE_ENUM)) + return f->store(x+1, 0); + else + return 1; + } virtual ~User_table_tabular() {} private: @@ -1416,6 +1434,10 @@ class User_table_json: public User_table { return get_str_value(root, "default_role"); } int set_default_role (const char *s, size_t l) const { return set_str_value("default_role", s, l); } + bool get_account_locked () const + { return get_bool_value("account_locked"); } + int set_account_locked (bool x) const + { return set_bool_value("account_locked", x); } ~User_table_json() {} private: @@ -2260,6 +2282,8 @@ static bool acl_load(THD *thd, const Grant_tables& tables) my_init_dynamic_array(&user.role_grants, sizeof(ACL_ROLE *), 0, 8, MYF(0)); + user.account_locked= user_table.get_account_locked(); + if (is_role) { if (is_invalid_role_name(username)) @@ -4327,6 +4351,13 @@ static int replace_user_table(THD *thd, const User_table &user_table, mqh_used= (mqh_used || lex->mqh.questions || lex->mqh.updates || lex->mqh.conn_per_hour || lex->mqh.user_conn || lex->mqh.max_statement_time != 0.0); + + if (lex->account_options.account_locked != ACCOUNTLOCK_UNSPECIFIED) + { + bool lock_value= lex->account_options.account_locked == ACCOUNTLOCK_LOCKED; + user_table.set_account_locked(lock_value); + new_acl_user.account_locked= lock_value; + } } if (old_row_exists) @@ -8780,6 +8811,9 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) add_user_parameters(&result, acl_user, false); + if (acl_user->account_locked) + result.append(STRING_WITH_LEN(" ACCOUNT LOCK")); + protocol->prepare_for_resend(); protocol->store(result.ptr(), result.length(), result.charset()); if (protocol->write()) @@ -13641,6 +13675,12 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) DBUG_RETURN(1); } + if (acl_user->account_locked) { + status_var_increment(denied_connections); + my_error(ER_ACCOUNT_HAS_BEEN_LOCKED, MYF(0)); + DBUG_RETURN(1); + } + /* Don't allow the user to connect if he has done too many queries. As we are testing max_user_connections == 0 here, it means that we diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 0fa1d96e626..d94e0b0fca5 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2939,6 +2939,27 @@ public: Explain_delete* save_explain_delete_data(MEM_ROOT *mem_root, THD *thd); }; +enum account_lock_type +{ + ACCOUNTLOCK_UNSPECIFIED, + ACCOUNTLOCK_LOCKED, + ACCOUNTLOCK_UNLOCKED +}; + +struct Account_options +{ + Account_options() + : account_locked(ACCOUNTLOCK_UNSPECIFIED) + { } + + void reset() + { + account_locked= ACCOUNTLOCK_UNSPECIFIED; + } + + account_lock_type account_locked; +}; + class Query_arena_memroot; /* The state of the lex parsing. This is saved in the THD struct */ @@ -3030,6 +3051,9 @@ public: */ LEX_USER *definer; + /* Used in ALTER/CREATE user to store account locking options */ + Account_options account_options; + Table_type table_type; /* Used for SHOW CREATE */ List ref_list; List users_list; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2077ea52557..52150fb0619 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1151,6 +1151,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); Non-reserved keywords */ +%token ACCOUNT_SYM /* MYSQL */ %token ACTION /* SQL-2003-N */ %token ADMIN_SYM /* SQL-2003-N */ %token ADDDATE_SYM /* MYSQL-FUNC */ @@ -2911,7 +2912,7 @@ create: Lex->pop_select(); //main select } | create_or_replace USER_SYM opt_if_not_exists clear_privileges - grant_list opt_require_clause opt_resource_options + grant_list opt_require_clause opt_resource_options opt_account_locking { if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3))) @@ -3318,6 +3319,7 @@ clear_privileges: lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; bzero((char *)&(lex->mqh),sizeof(lex->mqh)); + lex->account_options.reset(); } ; @@ -7979,7 +7981,7 @@ alter: } OPTIONS_SYM '(' server_options_list ')' { } /* ALTER USER foo is allowed for MySQL compatibility. */ | ALTER opt_if_exists USER_SYM clear_privileges grant_list - opt_require_clause opt_resource_options + opt_require_clause opt_resource_options opt_account_locking { Lex->create_info.set($2); Lex->sql_command= SQLCOM_ALTER_USER; @@ -8018,6 +8020,18 @@ alter: } ; +opt_account_locking: + /* Nothing */ {} + | ACCOUNT_SYM LOCK_SYM + { + Lex->account_options.account_locked= ACCOUNTLOCK_LOCKED; + } + | ACCOUNT_SYM UNLOCK_SYM + { + Lex->account_options.account_locked= ACCOUNTLOCK_UNLOCKED; + } + ; + ev_alter_on_schedule_completion: /* empty */ { $$= 0;} | ON SCHEDULE_SYM ev_schedule_time { $$= 1; } @@ -15855,6 +15869,7 @@ keyword_data_type: */ keyword_sp_var_and_label: ACTION + | ACCOUNT_SYM | ADDDATE_SYM | ADMIN_SYM | AFTER_SYM diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 4e14be598ce..99762e6aeb8 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -646,6 +646,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); Non-reserved keywords */ +%token ACCOUNT_SYM /* MYSQL */ %token ACTION /* SQL-2003-N */ %token ADMIN_SYM /* SQL-2003-N */ %token ADDDATE_SYM /* MYSQL-FUNC */ @@ -2417,7 +2418,7 @@ create: Lex->pop_select(); //main select } | create_or_replace USER_SYM opt_if_not_exists clear_privileges - grant_list opt_require_clause opt_resource_options + grant_list opt_require_clause opt_resource_options opt_account_locking { if (unlikely(Lex->set_command_with_check(SQLCOM_CREATE_USER, $1 | $3))) @@ -8009,7 +8010,7 @@ alter: } OPTIONS_SYM '(' server_options_list ')' { } /* ALTER USER foo is allowed for MySQL compatibility. */ | ALTER opt_if_exists USER_SYM clear_privileges grant_list - opt_require_clause opt_resource_options + opt_require_clause opt_resource_options opt_account_locking { Lex->create_info.set($2); Lex->sql_command= SQLCOM_ALTER_USER; @@ -8048,6 +8049,18 @@ alter: } ; +opt_account_locking: + /* Nothing */ {} + | ACCOUNT_SYM LOCK_SYM + { + Lex->account_options.account_locked= ACCOUNTLOCK_LOCKED; + } + | ACCOUNT_SYM UNLOCK_SYM + { + Lex->account_options.account_locked= ACCOUNTLOCK_UNLOCKED; + } + ; + ev_alter_on_schedule_completion: /* empty */ { $$= 0;} | ON SCHEDULE_SYM ev_schedule_time { $$= 1; } @@ -15943,6 +15956,7 @@ keyword_data_type: */ keyword_sp_var_and_label: ACTION + | ACCOUNT_SYM | ADDDATE_SYM | ADMIN_SYM | AFTER_SYM From e5701d83637d3d09976ef7cb2ebf489f63b81138 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 13 Feb 2019 20:35:11 +0100 Subject: [PATCH 89/91] cleanup: Account_options move account options from LEX to Account_options structure namely, mqh and ssl_* Also, use LEX_CSTRING for ssl_*/x509_* strings and move setting of ACL_USER::account_locked where it belongs --- sql/sql_acl.cc | 106 ++++++++++++++++++++++---------------------- sql/sql_lex.h | 10 ++--- sql/sql_yacc.yy | 52 +++++++++------------- sql/sql_yacc_ora.yy | 53 +++++++++------------- 4 files changed, 101 insertions(+), 120 deletions(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 9b457963a5e..05e522e6595 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3039,9 +3039,7 @@ static void acl_update_role(const char *rolename, ulong privileges) static int acl_user_update(THD *thd, ACL_USER *acl_user, uint nauth, const ACL_USER *from, const LEX_USER &combo, - const enum SSL_type ssl_type, - const char *ssl_cipher, const char *x509_issuer, - const char *x509_subject, const USER_RESOURCES *mqh, + const Account_options &options, const ulong privileges) { if (from) @@ -3077,23 +3075,27 @@ static int acl_user_update(THD *thd, ACL_USER *acl_user, uint nauth, } acl_user->access= privileges; - if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) - acl_user->user_resource.questions= mqh->questions; - if (mqh->specified_limits & USER_RESOURCES::UPDATES_PER_HOUR) - acl_user->user_resource.updates= mqh->updates; - if (mqh->specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR) - acl_user->user_resource.conn_per_hour= mqh->conn_per_hour; - if (mqh->specified_limits & USER_RESOURCES::USER_CONNECTIONS) - acl_user->user_resource.user_conn= mqh->user_conn; - if (mqh->specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) - acl_user->user_resource.max_statement_time= mqh->max_statement_time; - if (ssl_type != SSL_TYPE_NOT_SPECIFIED) + if (options.specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) + acl_user->user_resource.questions= options.questions; + if (options.specified_limits & USER_RESOURCES::UPDATES_PER_HOUR) + acl_user->user_resource.updates= options.updates; + if (options.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR) + acl_user->user_resource.conn_per_hour= options.conn_per_hour; + if (options.specified_limits & USER_RESOURCES::USER_CONNECTIONS) + acl_user->user_resource.user_conn= options.user_conn; + if (options.specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) + acl_user->user_resource.max_statement_time= options.max_statement_time; + if (options.ssl_type != SSL_TYPE_NOT_SPECIFIED) { - acl_user->ssl_type= ssl_type; - acl_user->ssl_cipher= safe_strdup_root(&acl_memroot, ssl_cipher); - acl_user->x509_issuer= safe_strdup_root(&acl_memroot, safe_str(x509_issuer)); - acl_user->x509_subject= safe_strdup_root(&acl_memroot, safe_str(x509_subject)); + acl_user->ssl_type= options.ssl_type; + acl_user->ssl_cipher= safe_strdup_root(&acl_memroot, options.ssl_cipher.str); + acl_user->x509_issuer= safe_strdup_root(&acl_memroot, + safe_str(options.x509_issuer.str)); + acl_user->x509_subject= safe_strdup_root(&acl_memroot, + safe_str(options.x509_subject.str)); } + if (options.account_locked != ACCOUNTLOCK_UNSPECIFIED) + acl_user->account_locked= options.account_locked == ACCOUNTLOCK_LOCKED; return 0; } @@ -4296,9 +4298,7 @@ static int replace_user_table(THD *thd, const User_table &user_table, } if (acl_user_update(thd, &new_acl_user, nauth, old_row_exists ? old_acl_user : NULL, - *combo, lex->ssl_type, lex->ssl_cipher, - lex->x509_issuer, lex->x509_subject, &lex->mqh, - rights)) + *combo, lex->account_options, rights)) goto end; if (user_table.set_auth(new_acl_user)) @@ -4309,55 +4309,54 @@ static int replace_user_table(THD *thd, const User_table &user_table, DBUG_RETURN(1); } - switch (lex->ssl_type) { + switch (lex->account_options.ssl_type) { case SSL_TYPE_NOT_SPECIFIED: break; case SSL_TYPE_NONE: case SSL_TYPE_ANY: case SSL_TYPE_X509: - user_table.set_ssl_type(lex->ssl_type); + user_table.set_ssl_type(lex->account_options.ssl_type); user_table.set_ssl_cipher("", 0); user_table.set_x509_issuer("", 0); user_table.set_x509_subject("", 0); break; case SSL_TYPE_SPECIFIED: - user_table.set_ssl_type(lex->ssl_type); - if (lex->ssl_cipher) - user_table.set_ssl_cipher(lex->ssl_cipher, strlen(lex->ssl_cipher)); + user_table.set_ssl_type(lex->account_options.ssl_type); + if (lex->account_options.ssl_cipher.str) + user_table.set_ssl_cipher(lex->account_options.ssl_cipher.str, + lex->account_options.ssl_cipher.length); else user_table.set_ssl_cipher("", 0); - if (lex->x509_issuer) - user_table.set_x509_issuer(lex->x509_issuer, strlen(lex->x509_issuer)); + if (lex->account_options.x509_issuer.str) + user_table.set_x509_issuer(lex->account_options.x509_issuer.str, + lex->account_options.x509_issuer.length); else user_table.set_x509_issuer("", 0); - if (lex->x509_subject) - user_table.set_x509_subject(lex->x509_subject, strlen(lex->x509_subject)); + if (lex->account_options.x509_subject.str) + user_table.set_x509_subject(lex->account_options.x509_subject.str, + lex->account_options.x509_subject.length); else user_table.set_x509_subject("", 0); break; } - if (lex->mqh.specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) - user_table.set_max_questions(lex->mqh.questions); - if (lex->mqh.specified_limits & USER_RESOURCES::UPDATES_PER_HOUR) - user_table.set_max_updates(lex->mqh.updates); - if (lex->mqh.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR) - user_table.set_max_connections(lex->mqh.conn_per_hour); - if (lex->mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS) - user_table.set_max_user_connections(lex->mqh.user_conn); - if (lex->mqh.specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) - user_table.set_max_statement_time(lex->mqh.max_statement_time); + if (lex->account_options.specified_limits & USER_RESOURCES::QUERIES_PER_HOUR) + user_table.set_max_questions(lex->account_options.questions); + if (lex->account_options.specified_limits & USER_RESOURCES::UPDATES_PER_HOUR) + user_table.set_max_updates(lex->account_options.updates); + if (lex->account_options.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR) + user_table.set_max_connections(lex->account_options.conn_per_hour); + if (lex->account_options.specified_limits & USER_RESOURCES::USER_CONNECTIONS) + user_table.set_max_user_connections(lex->account_options.user_conn); + if (lex->account_options.specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) + user_table.set_max_statement_time(lex->account_options.max_statement_time); - mqh_used= (mqh_used || lex->mqh.questions || lex->mqh.updates || - lex->mqh.conn_per_hour || lex->mqh.user_conn || - lex->mqh.max_statement_time != 0.0); + mqh_used= (mqh_used || lex->account_options.questions || lex->account_options.updates || + lex->account_options.conn_per_hour || lex->account_options.user_conn || + lex->account_options.max_statement_time != 0.0); if (lex->account_options.account_locked != ACCOUNTLOCK_UNSPECIFIED) - { - bool lock_value= lex->account_options.account_locked == ACCOUNTLOCK_LOCKED; - user_table.set_account_locked(lock_value); - new_acl_user.account_locked= lock_value; - } + user_table.set_account_locked(new_acl_user.account_locked); } if (old_row_exists) @@ -6543,8 +6542,11 @@ static bool merge_one_role_privileges(ACL_ROLE *grantee) static bool has_auth(LEX_USER *user, LEX *lex) { return user->has_auth() || - lex->ssl_type != SSL_TYPE_NOT_SPECIFIED || lex->ssl_cipher || - lex->x509_issuer || lex->x509_subject || lex->mqh.specified_limits; + lex->account_options.ssl_type != SSL_TYPE_NOT_SPECIFIED || + lex->account_options.ssl_cipher.str || + lex->account_options.x509_issuer.str || + lex->account_options.x509_subject.str || + lex->account_options.specified_limits; } static bool copy_and_check_auth(LEX_USER *to, LEX_USER *from, THD *thd) @@ -11240,9 +11242,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, if (user_list.push_back(combo, thd->mem_root)) DBUG_RETURN(TRUE); - thd->lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - thd->lex->ssl_cipher= thd->lex->x509_subject= thd->lex->x509_issuer= 0; - bzero(&thd->lex->mqh, sizeof(thd->lex->mqh)); + thd->lex->account_options.reset(); /* Only care about whether the operation failed or succeeded diff --git a/sql/sql_lex.h b/sql/sql_lex.h index d94e0b0fca5..fc451b21816 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2946,7 +2946,7 @@ enum account_lock_type ACCOUNTLOCK_UNLOCKED }; -struct Account_options +struct Account_options: public USER_RESOURCES { Account_options() : account_locked(ACCOUNTLOCK_UNSPECIFIED) @@ -2954,9 +2954,12 @@ struct Account_options void reset() { - account_locked= ACCOUNTLOCK_UNSPECIFIED; + bzero(this, sizeof(*this)); + ssl_type= SSL_TYPE_NOT_SPECIFIED; } + enum SSL_type ssl_type; // defined in violite.h + LEX_CSTRING x509_subject, x509_issuer, ssl_cipher; account_lock_type account_locked; }; @@ -3019,7 +3022,6 @@ public: const char *help_arg; const char *backup_dir; /* For RESTORE/BACKUP */ const char* to_log; /* For PURGE MASTER LOGS TO */ - const char* x509_subject,*x509_issuer,*ssl_cipher; String *wild; /* Wildcard in SHOW {something} LIKE 'wild'*/ sql_exchange *exchange; select_result *result; @@ -3125,7 +3127,6 @@ public: LEX_MASTER_INFO mi; // used by CHANGE MASTER LEX_SERVER_OPTIONS server_options; LEX_CSTRING relay_log_connection_name; - USER_RESOURCES mqh; LEX_RESET_SLAVE reset_slave_info; ulonglong type; ulong next_binlog_file_number; @@ -3163,7 +3164,6 @@ public: */ bool parse_vcol_expr; - enum SSL_type ssl_type; // defined in violite.h enum enum_duplicates duplicates; enum enum_tx_isolation tx_isolation; enum enum_ha_read_modes ha_read_mode; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 52150fb0619..d0b357d3187 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3316,9 +3316,6 @@ clear_privileges: lex->grant= lex->grant_tot_col= 0; lex->all_privileges= 0; lex->first_select_lex()->db= null_clex_str; - lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; - bzero((char *)&(lex->mqh),sizeof(lex->mqh)); lex->account_options.reset(); } ; @@ -17071,23 +17068,23 @@ require_list_element: SUBJECT_SYM TEXT_STRING { LEX *lex=Lex; - if (unlikely(lex->x509_subject)) + if (lex->account_options.x509_subject.str) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SUBJECT")); - lex->x509_subject=$2.str; + lex->account_options.x509_subject= $2; } | ISSUER_SYM TEXT_STRING { LEX *lex=Lex; - if (unlikely(lex->x509_issuer)) + if (lex->account_options.x509_issuer.str) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "ISSUER")); - lex->x509_issuer=$2.str; + lex->account_options.x509_issuer= $2; } | CIPHER_SYM TEXT_STRING { LEX *lex=Lex; - if (unlikely(lex->ssl_cipher)) + if (lex->account_options.ssl_cipher.str) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CIPHER")); - lex->ssl_cipher=$2.str; + lex->account_options.ssl_cipher= $2; } ; @@ -17284,52 +17281,47 @@ opt_require_clause: /* empty */ | REQUIRE_SYM require_list { - Lex->ssl_type=SSL_TYPE_SPECIFIED; + Lex->account_options.ssl_type= SSL_TYPE_SPECIFIED; } | REQUIRE_SYM SSL_SYM { - Lex->ssl_type=SSL_TYPE_ANY; + Lex->account_options.ssl_type= SSL_TYPE_ANY; } | REQUIRE_SYM X509_SYM { - Lex->ssl_type=SSL_TYPE_X509; + Lex->account_options.ssl_type= SSL_TYPE_X509; } | REQUIRE_SYM NONE_SYM { - Lex->ssl_type=SSL_TYPE_NONE; + Lex->account_options.ssl_type= SSL_TYPE_NONE; } ; resource_option: MAX_QUERIES_PER_HOUR ulong_num { - LEX *lex=Lex; - lex->mqh.questions=$2; - lex->mqh.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR; + Lex->account_options.questions=$2; + Lex->account_options.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR; } | MAX_UPDATES_PER_HOUR ulong_num { - LEX *lex=Lex; - lex->mqh.updates=$2; - lex->mqh.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR; + Lex->account_options.updates=$2; + Lex->account_options.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR; } | MAX_CONNECTIONS_PER_HOUR ulong_num { - LEX *lex=Lex; - lex->mqh.conn_per_hour= $2; - lex->mqh.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR; + Lex->account_options.conn_per_hour= $2; + Lex->account_options.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR; } | MAX_USER_CONNECTIONS_SYM int_num { - LEX *lex=Lex; - lex->mqh.user_conn= $2; - lex->mqh.specified_limits|= USER_RESOURCES::USER_CONNECTIONS; + Lex->account_options.user_conn= $2; + Lex->account_options.specified_limits|= USER_RESOURCES::USER_CONNECTIONS; } | MAX_STATEMENT_TIME_SYM NUM_literal { - LEX *lex=Lex; - lex->mqh.max_statement_time= $2->val_real(); - lex->mqh.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME; + Lex->account_options.max_statement_time= $2->val_real(); + Lex->account_options.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME; } ; @@ -17528,9 +17520,7 @@ definer: DEFINER_SYM '=' user_or_role { Lex->definer= $3; - Lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - Lex->ssl_cipher= Lex->x509_subject= Lex->x509_issuer= 0; - bzero(&(Lex->mqh), sizeof(Lex->mqh)); + Lex->account_options.reset(); } ; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 99762e6aeb8..4d05767b1be 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -3040,9 +3040,7 @@ clear_privileges: lex->grant= lex->grant_tot_col= 0; lex->all_privileges= 0; lex->first_select_lex()->db= null_clex_str; - lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; - bzero((char *)&(lex->mqh),sizeof(lex->mqh)); + lex->account_options.reset(); } ; @@ -17207,23 +17205,23 @@ require_list_element: SUBJECT_SYM TEXT_STRING { LEX *lex=Lex; - if (unlikely(lex->x509_subject)) + if (lex->account_options.x509_subject.str) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SUBJECT")); - lex->x509_subject=$2.str; + lex->account_options.x509_subject= $2; } | ISSUER_SYM TEXT_STRING { LEX *lex=Lex; - if (unlikely(lex->x509_issuer)) + if (lex->account_options.x509_issuer.str) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "ISSUER")); - lex->x509_issuer=$2.str; + lex->account_options.x509_issuer= $2; } | CIPHER_SYM TEXT_STRING { LEX *lex=Lex; - if (unlikely(lex->ssl_cipher)) + if (lex->account_options.ssl_cipher.str) my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CIPHER")); - lex->ssl_cipher=$2.str; + lex->account_options.ssl_cipher= $2; } ; @@ -17420,52 +17418,47 @@ opt_require_clause: /* empty */ | REQUIRE_SYM require_list { - Lex->ssl_type=SSL_TYPE_SPECIFIED; + Lex->account_options.ssl_type= SSL_TYPE_SPECIFIED; } | REQUIRE_SYM SSL_SYM { - Lex->ssl_type=SSL_TYPE_ANY; + Lex->account_options.ssl_type= SSL_TYPE_ANY; } | REQUIRE_SYM X509_SYM { - Lex->ssl_type=SSL_TYPE_X509; + Lex->account_options.ssl_type= SSL_TYPE_X509; } | REQUIRE_SYM NONE_SYM { - Lex->ssl_type=SSL_TYPE_NONE; + Lex->account_options.ssl_type= SSL_TYPE_NONE; } ; resource_option: MAX_QUERIES_PER_HOUR ulong_num { - LEX *lex=Lex; - lex->mqh.questions=$2; - lex->mqh.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR; + Lex->account_options.questions=$2; + Lex->account_options.specified_limits|= USER_RESOURCES::QUERIES_PER_HOUR; } | MAX_UPDATES_PER_HOUR ulong_num { - LEX *lex=Lex; - lex->mqh.updates=$2; - lex->mqh.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR; + Lex->account_options.updates=$2; + Lex->account_options.specified_limits|= USER_RESOURCES::UPDATES_PER_HOUR; } | MAX_CONNECTIONS_PER_HOUR ulong_num { - LEX *lex=Lex; - lex->mqh.conn_per_hour= $2; - lex->mqh.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR; + Lex->account_options.conn_per_hour= $2; + Lex->account_options.specified_limits|= USER_RESOURCES::CONNECTIONS_PER_HOUR; } | MAX_USER_CONNECTIONS_SYM int_num { - LEX *lex=Lex; - lex->mqh.user_conn= $2; - lex->mqh.specified_limits|= USER_RESOURCES::USER_CONNECTIONS; + Lex->account_options.user_conn= $2; + Lex->account_options.specified_limits|= USER_RESOURCES::USER_CONNECTIONS; } | MAX_STATEMENT_TIME_SYM NUM_literal { - LEX *lex=Lex; - lex->mqh.max_statement_time= $2->val_real(); - lex->mqh.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME; + Lex->account_options.max_statement_time= $2->val_real(); + Lex->account_options.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME; } ; @@ -17665,9 +17658,7 @@ definer: DEFINER_SYM '=' user_or_role { Lex->definer= $3; - Lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - Lex->ssl_cipher= Lex->x509_subject= Lex->x509_issuer= 0; - bzero(&(Lex->mqh), sizeof(Lex->mqh)); + Lex->account_options.reset(); } ; From ea0be9e2d63467064292559762887495772240fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 14 Feb 2019 20:17:14 +0200 Subject: [PATCH 90/91] MDEV-15564 Avoid table rebuild in ALTER TABLE on collation or charset changes Allow ALGORITHM=INSTANT (or avoid touching any data) when changing the collation, or in some cases, the character set, of a non-indexed CHAR or VARCHAR column. There is no penalty for subsequent DDL or DML operations, and compatibility with older MariaDB versions will be unaffected. Character sets may be changed when the old encoding is compatible with the new one. For example, changing from ASCII to anything ASCII-based, or from 3-byte to 4-byte UTF-8 can sometimes be performed instantly. This is joint work with Eugene Kosov. The test cases as well as ALTER_CONVERT_TO, charsets_are_compatible(), Type_handler::Charsets_are_compatible() are his work. The Field_str::is_equal(), Field_varstring::is_equal() and the InnoDB changes were mostly rewritten by me due to conflicts with MDEV-15563. Limitations: Changes of indexed columns will still require ALGORITHM=COPY. We should allow ALGORITHM=NOCOPY and allow the indexes to be rebuilt inside the storage engine, without copying the entire table. Instant column size changes (in bytes) are not supported by all storage engines. Instant CHAR column changes are only allowed for InnoDB ROW_FORMAT=REDUNDANT. We could allow this for InnoDB when the CHAR internally uses a variable-length encoding, say, when converting from 3-byte UTF-8 to 4-byte UTF-8. Instant VARCHAR column changes are allowed for InnoDB ROW_FORMAT=REDUNDANT, and for others only if the size in bytes does not change from 128..255 bytes to more than 256 bytes. Inside InnoDB, this slightly changes the way how MDEV-15563 works and fixes the result of the innodb.instant_alter_extend test. We change the way how ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT is handled. All column extension, type changes and renaming now go through a common route, except when ctx->is_instant() is in effect, for example, instant ADD or DROP COLUMN has been initiated. Only in that case we will go through innobase_instant_try() and rewrite all column metadata. get_type(field, prtype, mtype, len): Convert a SQL data type into InnoDB column metadata. innobase_rename_column_try(): Remove the update of SYS_COLUMNS. innobase_rename_or_enlarge_column_try(): New function, replacing part of innobase_rename_column_try() and all of innobase_enlarge_column_try(). Also changes column types. innobase_rename_or_enlarge_columns_cache(): Also change the column type. --- .../r/instant_alter_charset,redundant.rdiff | 28 + .../innodb/r/instant_alter_charset.result | 1812 +++++++++++++++++ .../innodb/r/instant_alter_extend,utf8.rdiff | 4 +- .../innodb/r/instant_alter_extend.result | 4 +- .../suite/innodb/t/instant_alter_charset.test | 538 +++++ .../suite/innodb/t/instant_alter_extend.test | 44 +- sql/field.cc | 101 +- sql/handler.h | 2 + sql/sql_type.cc | 46 + sql/sql_type.h | 4 + sql/sql_yacc.yy | 2 +- sql/sql_yacc_ora.yy | 2 +- storage/innobase/handler/handler0alter.cc | 296 +-- 13 files changed, 2676 insertions(+), 207 deletions(-) create mode 100644 mysql-test/suite/innodb/r/instant_alter_charset,redundant.rdiff create mode 100644 mysql-test/suite/innodb/r/instant_alter_charset.result create mode 100644 mysql-test/suite/innodb/t/instant_alter_charset.test diff --git a/mysql-test/suite/innodb/r/instant_alter_charset,redundant.rdiff b/mysql-test/suite/innodb/r/instant_alter_charset,redundant.rdiff new file mode 100644 index 00000000000..9a8dcd45e36 --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_charset,redundant.rdiff @@ -0,0 +1,28 @@ +--- instant_alter_charset.result ++++ instant_alter_charset,redundant.result +@@ -143,7 +143,7 @@ + drop index ab, + add unique key ab(a,c), + algorithm=instant; +-ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY ++ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY + drop table key_part_change; + create table key_part_change_and_rename ( + a char(100) charset ascii, +@@ -156,7 +156,7 @@ + drop index ab, + add unique key ab(a,b), + algorithm=instant; +-ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY ++ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY + drop table key_part_change_and_rename; + create table enum_and_set ( + a enum('one', 'two') charset utf8mb3, +@@ -254,7 +254,6 @@ + alter table boundary_255 + modify b varchar(200) charset utf8mb3, + algorithm=instant; +-ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY + alter table boundary_255 + modify c varchar(300) charset utf8mb3, + algorithm=instant; diff --git a/mysql-test/suite/innodb/r/instant_alter_charset.result b/mysql-test/suite/innodb/r/instant_alter_charset.result new file mode 100644 index 00000000000..268848f31ec --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_alter_charset.result @@ -0,0 +1,1812 @@ +set names utf8; +create table no_rebuild ( +a char(150) charset utf8mb3 collate utf8mb3_general_ci +) engine=innodb; +create table rebuild ( +a varchar(150) charset ascii +) engine=innodb; +set @id = (select table_id from information_schema.innodb_sys_tables +where name = 'test/no_rebuild'); +select name, prtype, len from information_schema.innodb_sys_columns +where table_id = @id; +name prtype len +a 2162942 450 +select c.prtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id +where t.name = 'test/rebuild' and c.name = 'a'; +prtype len +720911 150 +alter table no_rebuild +change a a char(150) charset utf8mb3 collate utf8mb3_spanish_ci, +algorithm=inplace; +alter table rebuild +change a a varchar(150) charset latin1 not null default 'asdf', +algorithm=inplace; +select name, prtype, len from information_schema.innodb_sys_columns +where table_id = @id; +name prtype len +a 13041918 450 +select c.prtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id +where t.name = 'test/rebuild' and c.name = 'a'; +prtype len +524559 150 +drop table no_rebuild, rebuild; +create table supported_types ( +id int primary key auto_increment, +a varchar(150) charset ascii, +b text(150) charset ascii, +c text charset ascii, +d tinytext charset ascii, +e mediumtext charset ascii, +f longtext charset ascii +) engine=innodb; +alter table supported_types +convert to charset latin1, +algorithm=instant; +drop table supported_types; +create table various_cases ( +a char(150) charset ascii, +b varchar(150) as (a) virtual, +c varchar(150) as (a) persistent +) engine=innodb; +alter table various_cases +change a a char(150) charset latin1, +algorithm=inplace; +alter table various_cases +change a a varchar(222), +algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table various_cases +change b b varchar(150) as (a) virtual, +algorithm=inplace; +alter table various_cases +change c c varchar(150) as (a) persistent, +algorithm=inplace; +ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY +alter table various_cases +modify a char(150) charset utf8mb4, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table various_cases; +create table all_texts ( +a tinytext charset ascii, +b text charset ascii, +c mediumtext charset ascii, +d longtext charset ascii, +footer int +) engine=innodb; +alter table all_texts +convert to charset latin1 collate latin1_general_ci, +algorithm=instant; +drop table all_texts; +create table all_binaries ( +a tinyblob, +b blob, +c mediumblob, +d longblob, +e varbinary(150), +f binary(150) +) engine=innodb; +alter table all_binaries modify a tinytext, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_binaries modify b text, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_binaries modify c mediumtext, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_binaries modify d longtext, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_binaries modify e varchar(150), algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_binaries modify f char(150), algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table all_binaries; +create table all_strings ( +a tinytext, +b text, +c mediumtext, +d longtext, +e varchar(150), +f char(150) +) engine=innodb; +alter table all_strings modify a tinyblob, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify b blob, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify c mediumblob, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify d longblob, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify e varbinary(150), algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify f binary(150), algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify a tinytext charset binary, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify b text charset binary, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify c mediumtext charset binary, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify d longtext charset binary, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify e varchar(150) charset binary, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table all_strings modify f char(150) charset binary, algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table all_strings; +create table key_part_change ( +a char(150) charset ascii, +b char(150) charset ascii, +c char(150) charset ascii, +unique key ab (a,b) +) engine=innodb; +alter table key_part_change +modify a char(150) charset utf8mb4, +drop index ab, +add unique key ab(a,c), +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table key_part_change; +create table key_part_change_and_rename ( +a char(100) charset ascii, +b char(100) charset ascii, +unique key ab (a,b) +) engine=innodb; +alter table key_part_change_and_rename +change a b char(100) charset utf8mb4, +change b a char(100) charset utf8mb4, +drop index ab, +add unique key ab(a,b), +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table key_part_change_and_rename; +create table enum_and_set ( +a enum('one', 'two') charset utf8mb3, +b set('three', 'four') charset utf8mb3 +) engine=innodb; +alter table enum_and_set +modify a enum('one', 'two') charset utf8mb4, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table enum_and_set +modify b enum('three', 'four') charset utf8mb4, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table enum_and_set; +create table compressed ( +a varchar(255) charset utf8mb3 compressed +) engine=innodb; +insert into compressed values ('AAA'), ('bbb'), ('CCC'); +alter table compressed +modify a varchar(255) charset utf8mb4 compressed, +algorithm=instant; +select * from compressed; +a +AAA +bbb +CCC +check table compresed; +Table Op Msg_type Msg_text +test.compresed check Error Table 'test.compresed' doesn't exist +test.compresed check status Operation failed +drop table compressed; +create table key_part_bug ( +id int primary key auto_increment, +a varchar(150) charset utf8mb3 unique key +) engine=innodb; +alter table key_part_bug +modify a varchar(150) charset utf8mb4, +algorithm=instant; +drop table key_part_bug; +create table latin1_swedish_special_case ( +copy1 varchar(150) charset ascii collate ascii_general_ci, +copy2 char(150) charset ascii collate ascii_general_ci, +instant1 varchar(150) charset ascii collate ascii_general_ci, +instant2 char(150) charset ascii collate ascii_general_ci +) engine=innodb; +select c.name, c.prtype, c.mtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id +where t.name = 'test/latin1_swedish_special_case'; +name prtype mtype len +copy1 720911 12 150 +copy2 721150 13 150 +instant1 720911 12 150 +instant2 721150 13 150 +alter table latin1_swedish_special_case +modify copy1 varchar(150) charset latin1 collate latin1_swedish_ci, +modify copy2 char(150) charset latin1 collate latin1_swedish_ci, +algorithm=copy; +alter table latin1_swedish_special_case +modify instant1 varchar(150) charset latin1 collate latin1_swedish_ci, +modify instant2 char(150) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +select c.name, c.prtype, c.mtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id +where t.name = 'test/latin1_swedish_special_case'; +name prtype mtype len +copy1 524303 1 150 +copy2 524542 2 150 +instant1 524303 1 150 +instant2 524542 2 150 +alter table latin1_swedish_special_case +modify copy1 varchar(150) charset latin1 collate latin1_general_ci, +modify copy2 char(150) charset latin1 collate latin1_general_ci, +algorithm=copy; +alter table latin1_swedish_special_case +modify instant1 varchar(150) charset latin1 collate latin1_general_ci, +modify instant2 char(150) charset latin1 collate latin1_general_ci, +algorithm=instant; +select c.name, c.prtype, c.mtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id +where t.name = 'test/latin1_swedish_special_case'; +name prtype mtype len +copy1 3145743 12 150 +copy2 3145982 13 150 +instant1 3145743 12 150 +instant2 3145982 13 150 +drop table latin1_swedish_special_case; +create table regression (a varchar(100) charset utf8mb3 primary key, b int) engine=innodb; +alter table regression convert to character set utf8mb4; +drop table regression; +create table boundary_255 ( +a varchar(50) charset ascii, +b varchar(200) charset ascii, +c varchar(300) charset ascii +) engine=innodb; +alter table boundary_255 +modify a varchar(50) charset utf8mb3, +algorithm=instant; +alter table boundary_255 +modify b varchar(200) charset utf8mb3, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table boundary_255 +modify c varchar(300) charset utf8mb3, +algorithm=instant; +drop table boundary_255; +create table fully_compatible ( +id int auto_increment unique key, +from_charset char(255), +from_collate char(255), +to_charset char(255), +to_collate char(255) +); +insert into fully_compatible (from_charset, from_collate, to_charset, to_collate) values +('utf8mb3', 'utf8mb3_general_ci', 'utf8mb4', 'utf8mb4_general_ci'), +('utf8mb3', 'utf8mb3_bin', 'utf8mb4', 'utf8mb4_bin'), +('utf8mb3', 'utf8mb3_unicode_ci', 'utf8mb4', 'utf8mb4_unicode_ci'), +('utf8mb3', 'utf8mb3_icelandic_ci', 'utf8mb4', 'utf8mb4_icelandic_ci'), +('utf8mb3', 'utf8mb3_latvian_ci', 'utf8mb4', 'utf8mb4_latvian_ci'), +('utf8mb3', 'utf8mb3_romanian_ci', 'utf8mb4', 'utf8mb4_romanian_ci'), +('utf8mb3', 'utf8mb3_slovenian_ci', 'utf8mb4', 'utf8mb4_slovenian_ci'), +('utf8mb3', 'utf8mb3_polish_ci', 'utf8mb4', 'utf8mb4_polish_ci'), +('utf8mb3', 'utf8mb3_estonian_ci', 'utf8mb4', 'utf8mb4_estonian_ci'), +('utf8mb3', 'utf8mb3_spanish_ci', 'utf8mb4', 'utf8mb4_spanish_ci'), +('utf8mb3', 'utf8mb3_swedish_ci', 'utf8mb4', 'utf8mb4_swedish_ci'), +('utf8mb3', 'utf8mb3_turkish_ci', 'utf8mb4', 'utf8mb4_turkish_ci'), +('utf8mb3', 'utf8mb3_czech_ci', 'utf8mb4', 'utf8mb4_czech_ci'), +('utf8mb3', 'utf8mb3_danish_ci', 'utf8mb4', 'utf8mb4_danish_ci'), +('utf8mb3', 'utf8mb3_lithuanian_ci', 'utf8mb4', 'utf8mb4_lithuanian_ci'), +('utf8mb3', 'utf8mb3_slovak_ci', 'utf8mb4', 'utf8mb4_slovak_ci'), +('utf8mb3', 'utf8mb3_spanish2_ci', 'utf8mb4', 'utf8mb4_spanish2_ci'), +('utf8mb3', 'utf8mb3_roman_ci', 'utf8mb4', 'utf8mb4_roman_ci'), +('utf8mb3', 'utf8mb3_persian_ci', 'utf8mb4', 'utf8mb4_persian_ci'), +('utf8mb3', 'utf8mb3_esperanto_ci', 'utf8mb4', 'utf8mb4_esperanto_ci'), +('utf8mb3', 'utf8mb3_hungarian_ci', 'utf8mb4', 'utf8mb4_hungarian_ci'), +('utf8mb3', 'utf8mb3_sinhala_ci', 'utf8mb4', 'utf8mb4_sinhala_ci'), +('utf8mb3', 'utf8mb3_german2_ci', 'utf8mb4', 'utf8mb4_german2_ci'), +('utf8mb3', 'utf8mb3_croatian_mysql561_ci', 'utf8mb4', 'utf8mb4_croatian_mysql561_ci'), +('utf8mb3', 'utf8mb3_unicode_520_ci', 'utf8mb4', 'utf8mb4_unicode_520_ci'), +('utf8mb3', 'utf8mb3_vietnamese_ci', 'utf8mb4', 'utf8mb4_vietnamese_ci'), +('utf8mb3', 'utf8mb3_croatian_ci', 'utf8mb4', 'utf8mb4_croatian_ci'), +('utf8mb3', 'utf8mb3_myanmar_ci', 'utf8mb4', 'utf8mb4_myanmar_ci'), +('utf8mb3', 'utf8mb3_thai_520_w2', 'utf8mb4', 'utf8mb4_thai_520_w2'), +('utf8mb3', 'utf8mb3_general_nopad_ci', 'utf8mb4', 'utf8mb4_general_nopad_ci'), +('utf8mb3', 'utf8mb3_nopad_bin', 'utf8mb4', 'utf8mb4_nopad_bin'), +('utf8mb3', 'utf8mb3_unicode_nopad_ci', 'utf8mb4', 'utf8mb4_unicode_nopad_ci'), +('utf8mb3', 'utf8mb3_unicode_520_nopad_ci', 'utf8mb4', 'utf8mb4_unicode_520_nopad_ci'), +('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_general_ci'), +('ucs2', 'ucs2_unicode_ci', 'utf16', 'utf16_unicode_ci'), +('ucs2', 'ucs2_icelandic_ci', 'utf16', 'utf16_icelandic_ci'), +('ucs2', 'ucs2_latvian_ci', 'utf16', 'utf16_latvian_ci'), +('ucs2', 'ucs2_romanian_ci', 'utf16', 'utf16_romanian_ci'), +('ucs2', 'ucs2_slovenian_ci', 'utf16', 'utf16_slovenian_ci'), +('ucs2', 'ucs2_polish_ci', 'utf16', 'utf16_polish_ci'), +('ucs2', 'ucs2_estonian_ci', 'utf16', 'utf16_estonian_ci'), +('ucs2', 'ucs2_spanish_ci', 'utf16', 'utf16_spanish_ci'), +('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_general_ci'), +('ascii', 'ascii_general_ci', 'utf8mb3', 'utf8mb3_general_ci'), +('ascii', 'ascii_general_ci', 'utf8mb4', 'utf8mb4_general_ci'), +('ascii', 'ascii_general_ci', 'latin1', 'latin1_general_ci'), +('ascii', 'ascii_bin', 'latin1', 'latin1_bin'), +('ascii', 'ascii_nopad_bin', 'latin1', 'latin1_nopad_bin'), +('ascii', 'ascii_general_ci', 'latin2', 'latin2_general_ci'), +('ascii', 'ascii_general_ci', 'latin7', 'latin7_general_ci'), +('ascii', 'ascii_bin', 'koi8u', 'koi8u_bin'), +('ascii', 'ascii_bin', 'ujis', 'ujis_bin'), +('ascii', 'ascii_bin', 'big5', 'big5_bin'), +('ascii', 'ascii_bin', 'gbk', 'gbk_bin') +; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_general_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_general_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_general_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_general_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_bin, +b varchar(50) charset utf8mb3 collate utf8mb3_bin primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_bin, +modify b varchar(50) charset utf8mb4 collate utf8mb4_bin, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_unicode_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_unicode_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_unicode_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_icelandic_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_icelandic_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_icelandic_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_icelandic_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_latvian_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_latvian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_latvian_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_latvian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_romanian_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_romanian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_romanian_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_romanian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_slovenian_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_slovenian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_slovenian_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_slovenian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_polish_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_polish_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_polish_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_polish_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_estonian_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_estonian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_estonian_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_estonian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_spanish_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_spanish_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_spanish_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_spanish_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_swedish_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_swedish_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_turkish_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_turkish_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_turkish_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_turkish_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_czech_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_czech_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_czech_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_czech_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_danish_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_danish_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_lithuanian_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_lithuanian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_lithuanian_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_lithuanian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_slovak_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_slovak_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_slovak_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_slovak_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_spanish2_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_spanish2_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_spanish2_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_spanish2_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_roman_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_roman_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_roman_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_roman_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_persian_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_persian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_persian_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_persian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_esperanto_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_esperanto_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_esperanto_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_esperanto_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_hungarian_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_hungarian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_hungarian_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_hungarian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_sinhala_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_sinhala_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_sinhala_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_sinhala_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_german2_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_german2_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_german2_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_german2_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_croatian_mysql561_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_croatian_mysql561_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_croatian_mysql561_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_croatian_mysql561_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_unicode_520_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_unicode_520_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_520_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_unicode_520_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_vietnamese_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_vietnamese_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_croatian_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_croatian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_croatian_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_croatian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_myanmar_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_myanmar_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_myanmar_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_myanmar_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_thai_520_w2, +b varchar(50) charset utf8mb3 collate utf8mb3_thai_520_w2 primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_thai_520_w2, +modify b varchar(50) charset utf8mb4 collate utf8mb4_thai_520_w2, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_general_nopad_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_general_nopad_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_general_nopad_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_general_nopad_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_nopad_bin, +b varchar(50) charset utf8mb3 collate utf8mb3_nopad_bin primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_nopad_bin, +modify b varchar(50) charset utf8mb4 collate utf8mb4_nopad_bin, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_unicode_nopad_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_unicode_nopad_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_nopad_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_unicode_nopad_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_unicode_520_nopad_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_unicode_520_nopad_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_unicode_520_nopad_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_unicode_520_nopad_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_general_ci, +b varchar(50) charset ucs2 collate ucs2_general_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf16 collate utf16_general_ci, +modify b varchar(50) charset utf16 collate utf16_general_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_unicode_ci, +b varchar(50) charset ucs2 collate ucs2_unicode_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf16 collate utf16_unicode_ci, +modify b varchar(50) charset utf16 collate utf16_unicode_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_icelandic_ci, +b varchar(50) charset ucs2 collate ucs2_icelandic_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf16 collate utf16_icelandic_ci, +modify b varchar(50) charset utf16 collate utf16_icelandic_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_latvian_ci, +b varchar(50) charset ucs2 collate ucs2_latvian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf16 collate utf16_latvian_ci, +modify b varchar(50) charset utf16 collate utf16_latvian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_romanian_ci, +b varchar(50) charset ucs2 collate ucs2_romanian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf16 collate utf16_romanian_ci, +modify b varchar(50) charset utf16 collate utf16_romanian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_slovenian_ci, +b varchar(50) charset ucs2 collate ucs2_slovenian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf16 collate utf16_slovenian_ci, +modify b varchar(50) charset utf16 collate utf16_slovenian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_polish_ci, +b varchar(50) charset ucs2 collate ucs2_polish_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf16 collate utf16_polish_ci, +modify b varchar(50) charset utf16 collate utf16_polish_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_estonian_ci, +b varchar(50) charset ucs2 collate ucs2_estonian_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf16 collate utf16_estonian_ci, +modify b varchar(50) charset utf16 collate utf16_estonian_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_spanish_ci, +b varchar(50) charset ucs2 collate ucs2_spanish_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf16 collate utf16_spanish_ci, +modify b varchar(50) charset utf16 collate utf16_spanish_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_general_ci, +b varchar(50) charset ucs2 collate ucs2_general_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf16 collate utf16_general_ci, +modify b varchar(50) charset utf16 collate utf16_general_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb3 collate utf8mb3_general_ci, +modify b varchar(50) charset utf8mb3 collate utf8mb3_general_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_general_ci, +modify b varchar(50) charset utf8mb4 collate utf8mb4_general_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset latin1 collate latin1_general_ci, +modify b varchar(50) charset latin1 collate latin1_general_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_bin, +b varchar(50) charset ascii collate ascii_bin primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset latin1 collate latin1_bin, +modify b varchar(50) charset latin1 collate latin1_bin, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_nopad_bin, +b varchar(50) charset ascii collate ascii_nopad_bin primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset latin1 collate latin1_nopad_bin, +modify b varchar(50) charset latin1 collate latin1_nopad_bin, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset latin2 collate latin2_general_ci, +modify b varchar(50) charset latin2 collate latin2_general_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset latin7 collate latin7_general_ci, +modify b varchar(50) charset latin7 collate latin7_general_ci, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_bin, +b varchar(50) charset ascii collate ascii_bin primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset koi8u collate koi8u_bin, +modify b varchar(50) charset koi8u collate koi8u_bin, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_bin, +b varchar(50) charset ascii collate ascii_bin primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset ujis collate ujis_bin, +modify b varchar(50) charset ujis collate ujis_bin, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_bin, +b varchar(50) charset ascii collate ascii_bin primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset big5 collate big5_bin, +modify b varchar(50) charset big5 collate big5_bin, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_bin, +b varchar(50) charset ascii collate ascii_bin primary key +) engine=innodb; +insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); +alter table tmp +change a a varchar(50) charset gbk collate gbk_bin, +modify b varchar(50) charset gbk collate gbk_bin, +algorithm=instant; +check table tmp; +Table Op Msg_type Msg_text +test.tmp check status OK +drop table tmp; +drop table fully_compatible; +create table compatible_without_index ( +id int auto_increment unique key, +from_charset char(255), +from_collate char(255), +to_charset char(255), +to_collate char(255) +); +insert into compatible_without_index (from_charset, from_collate, to_charset, to_collate) values +('ascii', 'ascii_general_ci', 'utf8mb3', 'utf8mb3_swedish_ci'), +('ascii', 'ascii_bin', 'latin1', 'latin1_swedish_ci'), +('ascii', 'ascii_general_nopad_ci', 'latin1', 'latin1_swedish_ci'), +('ascii', 'ascii_nopad_bin', 'latin1', 'latin1_swedish_ci'), +('ascii', 'ascii_general_ci', 'koi8u', 'koi8u_bin'), +('ascii', 'ascii_general_nopad_ci', 'koi8u', 'koi8u_bin'), +('ascii', 'ascii_nopad_bin', 'koi8u', 'koi8u_bin'), +('ascii', 'ascii_general_ci', 'latin1', 'latin1_swedish_ci'), +('ascii', 'ascii_bin', 'utf8mb3', 'utf8mb3_swedish_ci'), +('ascii', 'ascii_general_nopad_ci', 'utf8mb3', 'utf8mb3_swedish_ci'), +('ascii', 'ascii_nopad_bin', 'utf8mb3', 'utf8mb3_swedish_ci'), +('ascii', 'ascii_general_ci', 'utf8mb4', 'utf8mb4_danish_ci'), +('ascii', 'ascii_bin', 'utf8mb4', 'utf8mb4_danish_ci'), +('ascii', 'ascii_general_nopad_ci', 'utf8mb4', 'utf8mb4_danish_ci'), +('ascii', 'ascii_nopad_bin', 'utf8mb4', 'utf8mb4_danish_ci'), +('utf8mb3', 'utf8mb3_general_ci', 'utf8mb4', 'utf8mb4_vietnamese_ci'), +('utf8mb3', 'utf8mb3_bin', 'utf8mb4', 'utf8mb4_vietnamese_ci'), +('utf8mb3', 'utf8mb3_general_nopad_ci', 'utf8mb4', 'utf8mb4_vietnamese_ci'), +('utf8mb3', 'utf8mb3_nopad_bin', 'utf8mb4', 'utf8mb4_vietnamese_ci'), +('ascii', 'ascii_general_ci', 'gbk', 'gbk_chinese_ci'), +('ascii', 'ascii_general_ci', 'gbk', 'gbk_chinese_nopad_ci'), +('ucs2', 'ucs2_myanmar_ci', 'utf16', 'utf16_thai_520_w2'), +('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_unicode_nopad_ci'), +('ucs2', 'ucs2_general_mysql500_ci', 'utf16', 'utf16_spanish2_ci'), +('ascii', 'ascii_general_ci', 'ascii', 'ascii_bin'), +('utf8mb3', 'utf8mb3_roman_ci', 'utf8mb3', 'utf8mb3_lithuanian_ci'), +('utf8mb4', 'utf8mb4_thai_520_w2', 'utf8mb4', 'utf8mb4_persian_ci'), +('utf8mb3', 'utf8mb3_myanmar_ci', 'utf8mb4', 'utf8mb4_german2_ci'), +('utf8mb3', 'utf8mb3_general_ci', 'utf8mb3', 'utf8mb3_unicode_ci'), +('latin1', 'latin1_general_cs', 'latin1', 'latin1_general_ci'), +('ascii', 'ascii_general_ci', 'ujis', 'ujis_japanese_ci'), +('ascii', 'ascii_general_ci', 'big5', 'big5_chinese_ci'), +('ascii', 'ascii_general_ci', 'latin2', 'latin2_croatian_ci'), +('ascii', 'ascii_general_ci', 'latin7', 'latin7_estonian_cs'), +('utf16', 'utf16_general_ci', 'utf16', 'utf16_german2_ci') +; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_bin, +b varchar(50) charset ascii collate ascii_bin unique key, +c varchar(50) charset ascii collate ascii_bin primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_nopad_ci, +b varchar(50) charset ascii collate ascii_general_nopad_ci unique key, +c varchar(50) charset ascii collate ascii_general_nopad_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_nopad_bin, +b varchar(50) charset ascii collate ascii_nopad_bin unique key, +c varchar(50) charset ascii collate ascii_nopad_bin primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset koi8u collate koi8u_bin, +algorithm=instant; +alter table tmp +modify b varchar(50) charset koi8u collate koi8u_bin, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset koi8u collate koi8u_bin, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_nopad_ci, +b varchar(50) charset ascii collate ascii_general_nopad_ci unique key, +c varchar(50) charset ascii collate ascii_general_nopad_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset koi8u collate koi8u_bin, +algorithm=instant; +alter table tmp +modify b varchar(50) charset koi8u collate koi8u_bin, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset koi8u collate koi8u_bin, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_nopad_bin, +b varchar(50) charset ascii collate ascii_nopad_bin unique key, +c varchar(50) charset ascii collate ascii_nopad_bin primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset koi8u collate koi8u_bin, +algorithm=instant; +alter table tmp +modify b varchar(50) charset koi8u collate koi8u_bin, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset koi8u collate koi8u_bin, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset latin1 collate latin1_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_bin, +b varchar(50) charset ascii collate ascii_bin unique key, +c varchar(50) charset ascii collate ascii_bin primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_nopad_ci, +b varchar(50) charset ascii collate ascii_general_nopad_ci unique key, +c varchar(50) charset ascii collate ascii_general_nopad_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_nopad_bin, +b varchar(50) charset ascii collate ascii_nopad_bin unique key, +c varchar(50) charset ascii collate ascii_nopad_bin primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb3 collate utf8mb3_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_bin, +b varchar(50) charset ascii collate ascii_bin unique key, +c varchar(50) charset ascii collate ascii_bin primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_nopad_ci, +b varchar(50) charset ascii collate ascii_general_nopad_ci unique key, +c varchar(50) charset ascii collate ascii_general_nopad_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_nopad_bin, +b varchar(50) charset ascii collate ascii_nopad_bin unique key, +c varchar(50) charset ascii collate ascii_nopad_bin primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb4 collate utf8mb4_danish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_general_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_general_ci unique key, +c varchar(50) charset utf8mb3 collate utf8mb3_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_bin, +b varchar(50) charset utf8mb3 collate utf8mb3_bin unique key, +c varchar(50) charset utf8mb3 collate utf8mb3_bin primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_general_nopad_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_general_nopad_ci unique key, +c varchar(50) charset utf8mb3 collate utf8mb3_general_nopad_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_nopad_bin, +b varchar(50) charset utf8mb3 collate utf8mb3_nopad_bin unique key, +c varchar(50) charset utf8mb3 collate utf8mb3_nopad_bin primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb4 collate utf8mb4_vietnamese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset gbk collate gbk_chinese_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset gbk collate gbk_chinese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset gbk collate gbk_chinese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset gbk collate gbk_chinese_nopad_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset gbk collate gbk_chinese_nopad_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset gbk collate gbk_chinese_nopad_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_myanmar_ci, +b varchar(50) charset ucs2 collate ucs2_myanmar_ci unique key, +c varchar(50) charset ucs2 collate ucs2_myanmar_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf16 collate utf16_thai_520_w2, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf16 collate utf16_thai_520_w2, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf16 collate utf16_thai_520_w2, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_general_ci, +b varchar(50) charset ucs2 collate ucs2_general_ci unique key, +c varchar(50) charset ucs2 collate ucs2_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf16 collate utf16_unicode_nopad_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf16 collate utf16_unicode_nopad_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf16 collate utf16_unicode_nopad_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ucs2 collate ucs2_general_mysql500_ci, +b varchar(50) charset ucs2 collate ucs2_general_mysql500_ci unique key, +c varchar(50) charset ucs2 collate ucs2_general_mysql500_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf16 collate utf16_spanish2_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf16 collate utf16_spanish2_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf16 collate utf16_spanish2_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset ascii collate ascii_bin, +algorithm=instant; +alter table tmp +modify b varchar(50) charset ascii collate ascii_bin, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset ascii collate ascii_bin, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_roman_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_roman_ci unique key, +c varchar(50) charset utf8mb3 collate utf8mb3_roman_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb3 collate utf8mb3_lithuanian_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb3 collate utf8mb3_lithuanian_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb3 collate utf8mb3_lithuanian_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb4 collate utf8mb4_thai_520_w2, +b varchar(50) charset utf8mb4 collate utf8mb4_thai_520_w2 unique key, +c varchar(50) charset utf8mb4 collate utf8mb4_thai_520_w2 primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_persian_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb4 collate utf8mb4_persian_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb4 collate utf8mb4_persian_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_myanmar_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_myanmar_ci unique key, +c varchar(50) charset utf8mb3 collate utf8mb3_myanmar_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb4 collate utf8mb4_german2_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb4 collate utf8mb4_german2_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb4 collate utf8mb4_german2_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset utf8mb3 collate utf8mb3_general_ci, +b varchar(50) charset utf8mb3 collate utf8mb3_general_ci unique key, +c varchar(50) charset utf8mb3 collate utf8mb3_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf8mb3 collate utf8mb3_unicode_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf8mb3 collate utf8mb3_unicode_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf8mb3 collate utf8mb3_unicode_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset latin1 collate latin1_general_cs, +b varchar(50) charset latin1 collate latin1_general_cs unique key, +c varchar(50) charset latin1 collate latin1_general_cs primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset latin1 collate latin1_general_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset latin1 collate latin1_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset latin1 collate latin1_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset ujis collate ujis_japanese_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset ujis collate ujis_japanese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset ujis collate ujis_japanese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset big5 collate big5_chinese_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset big5 collate big5_chinese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset big5 collate big5_chinese_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset latin2 collate latin2_croatian_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset latin2 collate latin2_croatian_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset latin2 collate latin2_croatian_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset ascii collate ascii_general_ci, +b varchar(50) charset ascii collate ascii_general_ci unique key, +c varchar(50) charset ascii collate ascii_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset latin7 collate latin7_estonian_cs, +algorithm=instant; +alter table tmp +modify b varchar(50) charset latin7 collate latin7_estonian_cs, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset latin7 collate latin7_estonian_cs, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(50) charset utf16 collate utf16_general_ci, +b varchar(50) charset utf16 collate utf16_general_ci unique key, +c varchar(50) charset utf16 collate utf16_general_ci primary key +) engine=innodb; +alter table tmp +change a a varchar(50) charset utf16 collate utf16_german2_ci, +algorithm=instant; +alter table tmp +modify b varchar(50) charset utf16 collate utf16_german2_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify c varchar(50) charset utf16 collate utf16_german2_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +drop table compatible_without_index; +create table fully_incompatible ( +id int auto_increment unique key, +from_charset char(255), +from_collate char(255), +to_charset char(255), +to_collate char(255) +); +insert into fully_incompatible (from_charset, from_collate, to_charset, to_collate) values +('utf8mb4', 'utf8mb4_general_ci', 'utf8mb3', 'utf8mb3_general_ci'), +('utf8mb4', 'utf8mb4_general_ci', 'ascii', 'ascii_general_ci'), +('utf8mb3', 'utf8mb3_general_ci', 'ascii', 'ascii_general_ci'), +('utf8mb3', 'utf8mb3_general_ci', 'latin1', 'latin1_general_ci'), +('utf16', 'utf16_general_ci', 'utf32', 'utf32_general_ci'), +('latin1', 'latin1_general_ci', 'ascii', 'ascii_general_ci'), +('ascii', 'ascii_general_ci', 'swe7', 'swe7_swedish_ci'), +('eucjpms', 'eucjpms_japanese_nopad_ci', 'geostd8', 'geostd8_general_ci'), +('latin1', 'latin1_general_ci', 'utf16', 'utf16_general_ci') +; +create table tmp ( +a varchar(150) charset utf8mb4 collate utf8mb4_general_ci, +b text(150) charset utf8mb4 collate utf8mb4_general_ci, +unique key b_idx (b(150)) +) engine=innodb; +alter table tmp +change a a varchar(150) charset utf8mb3 collate utf8mb3_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify b text charset utf8mb3 collate utf8mb3_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(150) charset utf8mb4 collate utf8mb4_general_ci, +b text(150) charset utf8mb4 collate utf8mb4_general_ci, +unique key b_idx (b(150)) +) engine=innodb; +alter table tmp +change a a varchar(150) charset ascii collate ascii_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify b text charset ascii collate ascii_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(150) charset utf8mb3 collate utf8mb3_general_ci, +b text(150) charset utf8mb3 collate utf8mb3_general_ci, +unique key b_idx (b(150)) +) engine=innodb; +alter table tmp +change a a varchar(150) charset ascii collate ascii_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify b text charset ascii collate ascii_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(150) charset utf8mb3 collate utf8mb3_general_ci, +b text(150) charset utf8mb3 collate utf8mb3_general_ci, +unique key b_idx (b(150)) +) engine=innodb; +alter table tmp +change a a varchar(150) charset latin1 collate latin1_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify b text charset latin1 collate latin1_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(150) charset utf16 collate utf16_general_ci, +b text(150) charset utf16 collate utf16_general_ci, +unique key b_idx (b(150)) +) engine=innodb; +alter table tmp +change a a varchar(150) charset utf32 collate utf32_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify b text charset utf32 collate utf32_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(150) charset latin1 collate latin1_general_ci, +b text(150) charset latin1 collate latin1_general_ci, +unique key b_idx (b(150)) +) engine=innodb; +alter table tmp +change a a varchar(150) charset ascii collate ascii_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify b text charset ascii collate ascii_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(150) charset ascii collate ascii_general_ci, +b text(150) charset ascii collate ascii_general_ci, +unique key b_idx (b(150)) +) engine=innodb; +alter table tmp +change a a varchar(150) charset swe7 collate swe7_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify b text charset swe7 collate swe7_swedish_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(150) charset eucjpms collate eucjpms_japanese_nopad_ci, +b text(150) charset eucjpms collate eucjpms_japanese_nopad_ci, +unique key b_idx (b(150)) +) engine=innodb; +alter table tmp +change a a varchar(150) charset geostd8 collate geostd8_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify b text charset geostd8 collate geostd8_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +create table tmp ( +a varchar(150) charset latin1 collate latin1_general_ci, +b text(150) charset latin1 collate latin1_general_ci, +unique key b_idx (b(150)) +) engine=innodb; +alter table tmp +change a a varchar(150) charset utf16 collate utf16_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +alter table tmp +modify b text charset utf16 collate utf16_general_ci, +algorithm=instant; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY +drop table tmp; +drop table fully_incompatible; diff --git a/mysql-test/suite/innodb/r/instant_alter_extend,utf8.rdiff b/mysql-test/suite/innodb/r/instant_alter_extend,utf8.rdiff index 9b7196ccf9a..ad7ad0e1c66 100644 --- a/mysql-test/suite/innodb/r/instant_alter_extend,utf8.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_extend,utf8.rdiff @@ -13,8 +13,8 @@ test.t check status OK call check_table('t'); name mtype prtype len --a 2 800FE 200 -+a 13 2100FE 600 +-a 2 800FE 220 ++a 13 2100FE 660 # Convert from VARCHAR to a bigger CHAR alter table t modify a varchar(200), algorithm=instant; ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY diff --git a/mysql-test/suite/innodb/r/instant_alter_extend.result b/mysql-test/suite/innodb/r/instant_alter_extend.result index 1798f47104a..227932c3aa3 100644 --- a/mysql-test/suite/innodb/r/instant_alter_extend.result +++ b/mysql-test/suite/innodb/r/instant_alter_extend.result @@ -51,7 +51,7 @@ Table Op Msg_type Msg_text test.t check status OK call check_table('t'); name mtype prtype len -a 2 800FE 200 +a 2 800FE 220 # Convert from VARCHAR to a bigger CHAR alter table t modify a varchar(200), algorithm=instant; ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY @@ -101,7 +101,7 @@ Table Op Msg_type Msg_text test.t check status OK call check_table('t'); name mtype prtype len -a 3 3F04FE 200 +a 3 3F04FE 220 # Convert from VARBINARY to a bigger BINARY alter table t modify a varbinary(220), algorithm=instant; ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY diff --git a/mysql-test/suite/innodb/t/instant_alter_charset.test b/mysql-test/suite/innodb/t/instant_alter_charset.test new file mode 100644 index 00000000000..82ab9f9eb94 --- /dev/null +++ b/mysql-test/suite/innodb/t/instant_alter_charset.test @@ -0,0 +1,538 @@ +--source include/innodb_row_format.inc +#--source include/innodb_page_size.inc + +--let $row_format= `SELECT @@GLOBAL.innodb_default_row_format` +set names utf8; + +create table no_rebuild ( + a char(150) charset utf8mb3 collate utf8mb3_general_ci +) engine=innodb; +create table rebuild ( + a varchar(150) charset ascii +) engine=innodb; + +set @id = (select table_id from information_schema.innodb_sys_tables + where name = 'test/no_rebuild'); +select name, prtype, len from information_schema.innodb_sys_columns + where table_id = @id; +select c.prtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id + where t.name = 'test/rebuild' and c.name = 'a'; +alter table no_rebuild + change a a char(150) charset utf8mb3 collate utf8mb3_spanish_ci, + algorithm=inplace; +alter table rebuild + change a a varchar(150) charset latin1 not null default 'asdf', + algorithm=inplace; +select name, prtype, len from information_schema.innodb_sys_columns + where table_id = @id; +select c.prtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id + where t.name = 'test/rebuild' and c.name = 'a'; + +drop table no_rebuild, rebuild; + +create table supported_types ( + id int primary key auto_increment, + a varchar(150) charset ascii, + b text(150) charset ascii, + c text charset ascii, + d tinytext charset ascii, + e mediumtext charset ascii, + f longtext charset ascii +) engine=innodb; + +alter table supported_types + convert to charset latin1, + algorithm=instant; + +drop table supported_types; + +create table various_cases ( + a char(150) charset ascii, + b varchar(150) as (a) virtual, + c varchar(150) as (a) persistent +) engine=innodb; + +alter table various_cases + change a a char(150) charset latin1, + algorithm=inplace; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table various_cases + change a a varchar(222), + algorithm=inplace; + +alter table various_cases + change b b varchar(150) as (a) virtual, + algorithm=inplace; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED +alter table various_cases + change c c varchar(150) as (a) persistent, + algorithm=inplace; + +# Can not grow storage in bytes from CHAR +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table various_cases + modify a char(150) charset utf8mb4, + algorithm=instant; + +drop table various_cases; + + +create table all_texts ( + a tinytext charset ascii, + b text charset ascii, + c mediumtext charset ascii, + d longtext charset ascii, + footer int +) engine=innodb; + +alter table all_texts + convert to charset latin1 collate latin1_general_ci, + algorithm=instant; + +drop table all_texts; + + +create table all_binaries ( + a tinyblob, + b blob, + c mediumblob, + d longblob, + e varbinary(150), + f binary(150) +) engine=innodb; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_binaries modify a tinytext, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_binaries modify b text, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_binaries modify c mediumtext, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_binaries modify d longtext, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_binaries modify e varchar(150), algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_binaries modify f char(150), algorithm=instant; + +drop table all_binaries; + +create table all_strings ( + a tinytext, + b text, + c mediumtext, + d longtext, + e varchar(150), + f char(150) +) engine=innodb; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify a tinyblob, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify b blob, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify c mediumblob, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify d longblob, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify e varbinary(150), algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify f binary(150), algorithm=instant; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify a tinytext charset binary, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify b text charset binary, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify c mediumtext charset binary, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify d longtext charset binary, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify e varchar(150) charset binary, algorithm=instant; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table all_strings modify f char(150) charset binary, algorithm=instant; + +drop table all_strings; + +create table key_part_change ( + a char(150) charset ascii, + b char(150) charset ascii, + c char(150) charset ascii, + unique key ab (a,b) +) engine=innodb; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table key_part_change + modify a char(150) charset utf8mb4, + drop index ab, + add unique key ab(a,c), + algorithm=instant; + +drop table key_part_change; + +create table key_part_change_and_rename ( + a char(100) charset ascii, + b char(100) charset ascii, + unique key ab (a,b) +) engine=innodb; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table key_part_change_and_rename + change a b char(100) charset utf8mb4, + change b a char(100) charset utf8mb4, + drop index ab, + add unique key ab(a,b), + algorithm=instant; + +drop table key_part_change_and_rename; + +create table enum_and_set ( + a enum('one', 'two') charset utf8mb3, + b set('three', 'four') charset utf8mb3 +) engine=innodb; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table enum_and_set + modify a enum('one', 'two') charset utf8mb4, + algorithm=instant; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table enum_and_set + modify b enum('three', 'four') charset utf8mb4, + algorithm=instant; + +drop table enum_and_set; + +create table compressed ( + a varchar(255) charset utf8mb3 compressed +) engine=innodb; + +insert into compressed values ('AAA'), ('bbb'), ('CCC'); + +alter table compressed + modify a varchar(255) charset utf8mb4 compressed, + algorithm=instant; + +select * from compressed; +check table compresed; + +drop table compressed; + +create table key_part_bug ( + id int primary key auto_increment, + a varchar(150) charset utf8mb3 unique key +) engine=innodb; + +alter table key_part_bug + modify a varchar(150) charset utf8mb4, + algorithm=instant; + +drop table key_part_bug; + + +create table latin1_swedish_special_case ( + copy1 varchar(150) charset ascii collate ascii_general_ci, + copy2 char(150) charset ascii collate ascii_general_ci, + instant1 varchar(150) charset ascii collate ascii_general_ci, + instant2 char(150) charset ascii collate ascii_general_ci +) engine=innodb; + +select c.name, c.prtype, c.mtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id + where t.name = 'test/latin1_swedish_special_case'; +alter table latin1_swedish_special_case + modify copy1 varchar(150) charset latin1 collate latin1_swedish_ci, + modify copy2 char(150) charset latin1 collate latin1_swedish_ci, + algorithm=copy; +alter table latin1_swedish_special_case + modify instant1 varchar(150) charset latin1 collate latin1_swedish_ci, + modify instant2 char(150) charset latin1 collate latin1_swedish_ci, + algorithm=instant; +select c.name, c.prtype, c.mtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id + where t.name = 'test/latin1_swedish_special_case'; +alter table latin1_swedish_special_case + modify copy1 varchar(150) charset latin1 collate latin1_general_ci, + modify copy2 char(150) charset latin1 collate latin1_general_ci, + algorithm=copy; +alter table latin1_swedish_special_case + modify instant1 varchar(150) charset latin1 collate latin1_general_ci, + modify instant2 char(150) charset latin1 collate latin1_general_ci, + algorithm=instant; +select c.name, c.prtype, c.mtype, c.len from information_schema.innodb_sys_columns as c inner join information_schema.innodb_sys_tables t on c.table_id = t.table_id + where t.name = 'test/latin1_swedish_special_case'; + +drop table latin1_swedish_special_case; + +create table regression (a varchar(100) charset utf8mb3 primary key, b int) engine=innodb; +alter table regression convert to character set utf8mb4; +drop table regression; + +# ROW_FORMAT=DYNAMIC limitation: +# size in bytes cannot be increased from less of equal that 255 to more than 255 +create table boundary_255 ( + a varchar(50) charset ascii, + b varchar(200) charset ascii, + c varchar(300) charset ascii +) engine=innodb; + +alter table boundary_255 + modify a varchar(50) charset utf8mb3, + algorithm=instant; + +if ($row_format == 'redundant') { +alter table boundary_255 + modify b varchar(200) charset utf8mb3, + algorithm=instant; +} +if ($row_format != 'redundant') { +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +alter table boundary_255 + modify b varchar(200) charset utf8mb3, + algorithm=instant; +} + +alter table boundary_255 + modify c varchar(300) charset utf8mb3, + algorithm=instant; + +drop table boundary_255; + +create table fully_compatible ( + id int auto_increment unique key, + from_charset char(255), + from_collate char(255), + to_charset char(255), + to_collate char(255) +); + +insert into fully_compatible (from_charset, from_collate, to_charset, to_collate) values + ('utf8mb3', 'utf8mb3_general_ci', 'utf8mb4', 'utf8mb4_general_ci'), + ('utf8mb3', 'utf8mb3_bin', 'utf8mb4', 'utf8mb4_bin'), + ('utf8mb3', 'utf8mb3_unicode_ci', 'utf8mb4', 'utf8mb4_unicode_ci'), + ('utf8mb3', 'utf8mb3_icelandic_ci', 'utf8mb4', 'utf8mb4_icelandic_ci'), + ('utf8mb3', 'utf8mb3_latvian_ci', 'utf8mb4', 'utf8mb4_latvian_ci'), + ('utf8mb3', 'utf8mb3_romanian_ci', 'utf8mb4', 'utf8mb4_romanian_ci'), + ('utf8mb3', 'utf8mb3_slovenian_ci', 'utf8mb4', 'utf8mb4_slovenian_ci'), + ('utf8mb3', 'utf8mb3_polish_ci', 'utf8mb4', 'utf8mb4_polish_ci'), + ('utf8mb3', 'utf8mb3_estonian_ci', 'utf8mb4', 'utf8mb4_estonian_ci'), + ('utf8mb3', 'utf8mb3_spanish_ci', 'utf8mb4', 'utf8mb4_spanish_ci'), + ('utf8mb3', 'utf8mb3_swedish_ci', 'utf8mb4', 'utf8mb4_swedish_ci'), + ('utf8mb3', 'utf8mb3_turkish_ci', 'utf8mb4', 'utf8mb4_turkish_ci'), + ('utf8mb3', 'utf8mb3_czech_ci', 'utf8mb4', 'utf8mb4_czech_ci'), + ('utf8mb3', 'utf8mb3_danish_ci', 'utf8mb4', 'utf8mb4_danish_ci'), + ('utf8mb3', 'utf8mb3_lithuanian_ci', 'utf8mb4', 'utf8mb4_lithuanian_ci'), + ('utf8mb3', 'utf8mb3_slovak_ci', 'utf8mb4', 'utf8mb4_slovak_ci'), + ('utf8mb3', 'utf8mb3_spanish2_ci', 'utf8mb4', 'utf8mb4_spanish2_ci'), + ('utf8mb3', 'utf8mb3_roman_ci', 'utf8mb4', 'utf8mb4_roman_ci'), + ('utf8mb3', 'utf8mb3_persian_ci', 'utf8mb4', 'utf8mb4_persian_ci'), + ('utf8mb3', 'utf8mb3_esperanto_ci', 'utf8mb4', 'utf8mb4_esperanto_ci'), + ('utf8mb3', 'utf8mb3_hungarian_ci', 'utf8mb4', 'utf8mb4_hungarian_ci'), + ('utf8mb3', 'utf8mb3_sinhala_ci', 'utf8mb4', 'utf8mb4_sinhala_ci'), + ('utf8mb3', 'utf8mb3_german2_ci', 'utf8mb4', 'utf8mb4_german2_ci'), + ('utf8mb3', 'utf8mb3_croatian_mysql561_ci', 'utf8mb4', 'utf8mb4_croatian_mysql561_ci'), + ('utf8mb3', 'utf8mb3_unicode_520_ci', 'utf8mb4', 'utf8mb4_unicode_520_ci'), + ('utf8mb3', 'utf8mb3_vietnamese_ci', 'utf8mb4', 'utf8mb4_vietnamese_ci'), + ('utf8mb3', 'utf8mb3_croatian_ci', 'utf8mb4', 'utf8mb4_croatian_ci'), + ('utf8mb3', 'utf8mb3_myanmar_ci', 'utf8mb4', 'utf8mb4_myanmar_ci'), + ('utf8mb3', 'utf8mb3_thai_520_w2', 'utf8mb4', 'utf8mb4_thai_520_w2'), + ('utf8mb3', 'utf8mb3_general_nopad_ci', 'utf8mb4', 'utf8mb4_general_nopad_ci'), + ('utf8mb3', 'utf8mb3_nopad_bin', 'utf8mb4', 'utf8mb4_nopad_bin'), + ('utf8mb3', 'utf8mb3_unicode_nopad_ci', 'utf8mb4', 'utf8mb4_unicode_nopad_ci'), + ('utf8mb3', 'utf8mb3_unicode_520_nopad_ci', 'utf8mb4', 'utf8mb4_unicode_520_nopad_ci'), + + ('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_general_ci'), + ('ucs2', 'ucs2_unicode_ci', 'utf16', 'utf16_unicode_ci'), + ('ucs2', 'ucs2_icelandic_ci', 'utf16', 'utf16_icelandic_ci'), + ('ucs2', 'ucs2_latvian_ci', 'utf16', 'utf16_latvian_ci'), + ('ucs2', 'ucs2_romanian_ci', 'utf16', 'utf16_romanian_ci'), + ('ucs2', 'ucs2_slovenian_ci', 'utf16', 'utf16_slovenian_ci'), + ('ucs2', 'ucs2_polish_ci', 'utf16', 'utf16_polish_ci'), + ('ucs2', 'ucs2_estonian_ci', 'utf16', 'utf16_estonian_ci'), + ('ucs2', 'ucs2_spanish_ci', 'utf16', 'utf16_spanish_ci'), + ('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_general_ci'), + + ('ascii', 'ascii_general_ci', 'utf8mb3', 'utf8mb3_general_ci'), + ('ascii', 'ascii_general_ci', 'utf8mb4', 'utf8mb4_general_ci'), + ('ascii', 'ascii_general_ci', 'latin1', 'latin1_general_ci'), + ('ascii', 'ascii_bin', 'latin1', 'latin1_bin'), + ('ascii', 'ascii_nopad_bin', 'latin1', 'latin1_nopad_bin'), + ('ascii', 'ascii_general_ci', 'latin2', 'latin2_general_ci'), + ('ascii', 'ascii_general_ci', 'latin7', 'latin7_general_ci'), + ('ascii', 'ascii_bin', 'koi8u', 'koi8u_bin'), + ('ascii', 'ascii_bin', 'ujis', 'ujis_bin'), + ('ascii', 'ascii_bin', 'big5', 'big5_bin'), + ('ascii', 'ascii_bin', 'gbk', 'gbk_bin') +; + +let $data_size = `select count(*) from fully_compatible`; +let $counter = 1; + +while ($counter <= $data_size) { + let $from_charset = `select from_charset from fully_compatible where id = $counter`; + let $from_collate = `select from_collate from fully_compatible where id = $counter`; + let $to_charset = `select to_charset from fully_compatible where id = $counter`; + let $to_collate = `select to_collate from fully_compatible where id = $counter`; + + eval create table tmp ( + a varchar(50) charset $from_charset collate $from_collate, + b varchar(50) charset $from_charset collate $from_collate primary key + ) engine=innodb; + + insert into tmp values ('AAA', 'AAA'), ('bbb', 'bbb'); + + eval alter table tmp + change a a varchar(50) charset $to_charset collate $to_collate, + modify b varchar(50) charset $to_charset collate $to_collate, + algorithm=instant; + + check table tmp; + + drop table tmp; + + inc $counter; +} + +drop table fully_compatible; + + +create table compatible_without_index ( + id int auto_increment unique key, + from_charset char(255), + from_collate char(255), + to_charset char(255), + to_collate char(255) +); + +insert into compatible_without_index (from_charset, from_collate, to_charset, to_collate) values + ('ascii', 'ascii_general_ci', 'utf8mb3', 'utf8mb3_swedish_ci'), + ('ascii', 'ascii_bin', 'latin1', 'latin1_swedish_ci'), + ('ascii', 'ascii_general_nopad_ci', 'latin1', 'latin1_swedish_ci'), + ('ascii', 'ascii_nopad_bin', 'latin1', 'latin1_swedish_ci'), + + ('ascii', 'ascii_general_ci', 'koi8u', 'koi8u_bin'), + ('ascii', 'ascii_general_nopad_ci', 'koi8u', 'koi8u_bin'), + ('ascii', 'ascii_nopad_bin', 'koi8u', 'koi8u_bin'), + + ('ascii', 'ascii_general_ci', 'latin1', 'latin1_swedish_ci'), + ('ascii', 'ascii_bin', 'utf8mb3', 'utf8mb3_swedish_ci'), + ('ascii', 'ascii_general_nopad_ci', 'utf8mb3', 'utf8mb3_swedish_ci'), + ('ascii', 'ascii_nopad_bin', 'utf8mb3', 'utf8mb3_swedish_ci'), + + ('ascii', 'ascii_general_ci', 'utf8mb4', 'utf8mb4_danish_ci'), + ('ascii', 'ascii_bin', 'utf8mb4', 'utf8mb4_danish_ci'), + ('ascii', 'ascii_general_nopad_ci', 'utf8mb4', 'utf8mb4_danish_ci'), + ('ascii', 'ascii_nopad_bin', 'utf8mb4', 'utf8mb4_danish_ci'), + + ('utf8mb3', 'utf8mb3_general_ci', 'utf8mb4', 'utf8mb4_vietnamese_ci'), + ('utf8mb3', 'utf8mb3_bin', 'utf8mb4', 'utf8mb4_vietnamese_ci'), + ('utf8mb3', 'utf8mb3_general_nopad_ci', 'utf8mb4', 'utf8mb4_vietnamese_ci'), + ('utf8mb3', 'utf8mb3_nopad_bin', 'utf8mb4', 'utf8mb4_vietnamese_ci'), + + ('ascii', 'ascii_general_ci', 'gbk', 'gbk_chinese_ci'), + ('ascii', 'ascii_general_ci', 'gbk', 'gbk_chinese_nopad_ci'), + + ('ucs2', 'ucs2_myanmar_ci', 'utf16', 'utf16_thai_520_w2'), + ('ucs2', 'ucs2_general_ci', 'utf16', 'utf16_unicode_nopad_ci'), + ('ucs2', 'ucs2_general_mysql500_ci', 'utf16', 'utf16_spanish2_ci'), + + ('ascii', 'ascii_general_ci', 'ascii', 'ascii_bin'), + ('utf8mb3', 'utf8mb3_roman_ci', 'utf8mb3', 'utf8mb3_lithuanian_ci'), + ('utf8mb4', 'utf8mb4_thai_520_w2', 'utf8mb4', 'utf8mb4_persian_ci'), + ('utf8mb3', 'utf8mb3_myanmar_ci', 'utf8mb4', 'utf8mb4_german2_ci'), + ('utf8mb3', 'utf8mb3_general_ci', 'utf8mb3', 'utf8mb3_unicode_ci'), + ('latin1', 'latin1_general_cs', 'latin1', 'latin1_general_ci'), + ('ascii', 'ascii_general_ci', 'ujis', 'ujis_japanese_ci'), + ('ascii', 'ascii_general_ci', 'big5', 'big5_chinese_ci'), + ('ascii', 'ascii_general_ci', 'latin2', 'latin2_croatian_ci'), + ('ascii', 'ascii_general_ci', 'latin7', 'latin7_estonian_cs'), + ('utf16', 'utf16_general_ci', 'utf16', 'utf16_german2_ci') +; + +let $data_size = `select count(*) from compatible_without_index`; +let $counter = 1; + +while ($counter <= $data_size) { + let $from_charset = `select from_charset from compatible_without_index where id = $counter`; + let $from_collate = `select from_collate from compatible_without_index where id = $counter`; + let $to_charset = `select to_charset from compatible_without_index where id = $counter`; + let $to_collate = `select to_collate from compatible_without_index where id = $counter`; + + eval create table tmp ( + a varchar(50) charset $from_charset collate $from_collate, + b varchar(50) charset $from_charset collate $from_collate unique key, + c varchar(50) charset $from_charset collate $from_collate primary key + ) engine=innodb; + + eval alter table tmp + change a a varchar(50) charset $to_charset collate $to_collate, + algorithm=instant; + + --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON + eval alter table tmp + modify b varchar(50) charset $to_charset collate $to_collate, + algorithm=instant; + + --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON + eval alter table tmp + modify c varchar(50) charset $to_charset collate $to_collate, + algorithm=instant; + + drop table tmp; + + inc $counter; +} + +drop table compatible_without_index; + + +create table fully_incompatible ( + id int auto_increment unique key, + from_charset char(255), + from_collate char(255), + to_charset char(255), + to_collate char(255) +); + +insert into fully_incompatible (from_charset, from_collate, to_charset, to_collate) values + ('utf8mb4', 'utf8mb4_general_ci', 'utf8mb3', 'utf8mb3_general_ci'), + ('utf8mb4', 'utf8mb4_general_ci', 'ascii', 'ascii_general_ci'), + ('utf8mb3', 'utf8mb3_general_ci', 'ascii', 'ascii_general_ci'), + ('utf8mb3', 'utf8mb3_general_ci', 'latin1', 'latin1_general_ci'), + ('utf16', 'utf16_general_ci', 'utf32', 'utf32_general_ci'), + ('latin1', 'latin1_general_ci', 'ascii', 'ascii_general_ci'), + ('ascii', 'ascii_general_ci', 'swe7', 'swe7_swedish_ci'), + ('eucjpms', 'eucjpms_japanese_nopad_ci', 'geostd8', 'geostd8_general_ci'), + ('latin1', 'latin1_general_ci', 'utf16', 'utf16_general_ci') +; + +let $data_size = `select count(*) from fully_incompatible`; +let $counter = 1; + +while ($counter <= $data_size) { + let $from_charset = `select from_charset from fully_incompatible where id = $counter`; + let $from_collate = `select from_collate from fully_incompatible where id = $counter`; + let $to_charset = `select to_charset from fully_incompatible where id = $counter`; + let $to_collate = `select to_collate from fully_incompatible where id = $counter`; + + eval create table tmp ( + a varchar(150) charset $from_charset collate $from_collate, + b text(150) charset $from_charset collate $from_collate, + unique key b_idx (b(150)) + ) engine=innodb; + + --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON + eval alter table tmp + change a a varchar(150) charset $to_charset collate $to_collate, + algorithm=instant; + + --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON + eval alter table tmp + modify b text charset $to_charset collate $to_collate, + algorithm=instant; + + drop table tmp; + + inc $counter; +} + +drop table fully_incompatible; diff --git a/mysql-test/suite/innodb/t/instant_alter_extend.test b/mysql-test/suite/innodb/t/instant_alter_extend.test index 4ffa39c4f13..80f82820afe 100644 --- a/mysql-test/suite/innodb/t/instant_alter_extend.test +++ b/mysql-test/suite/innodb/t/instant_alter_extend.test @@ -36,18 +36,15 @@ alter table t modify a char(255), algorithm=instant; alter table t modify a char(255), algorithm=copy; create or replace table t (a varchar(200)); -if ($have_debug) { ---disable_query_log ---disable_result_log -set debug_dbug= '+d,ib_instant_error'; ---error ER_RECORD_FILE_FULL -alter table t modify a char(200); -set debug_dbug= default; ---enable_query_log ---enable_result_log -} insert into t values (@bigval); insert into t values ('z'); +if ($have_debug) { +--disable_query_log +# This should not be reachable. +set @save_debug= @@SESSION.debug_dbug; +set debug_dbug= '+d,ib_instant_error'; +--enable_query_log +} alter table t modify a char(200), algorithm=instant; select count(a) from t where a = @bigval; select a, length(a) from t where a = 'z'; @@ -82,16 +79,6 @@ alter table t modify a binary(255), algorithm=instant; alter table t modify a binary(255), algorithm=copy; create or replace table t (a varbinary(200)); -if ($have_debug) { ---disable_query_log ---disable_result_log -set debug_dbug= '+d,ib_instant_error'; ---error ER_RECORD_FILE_FULL -alter table t modify a binary(200); -set debug_dbug= default; ---enable_query_log ---enable_result_log -} insert into t values (@bigval); insert into t values ('z'); alter table t modify a binary(200), algorithm=instant; @@ -122,16 +109,6 @@ call check_table('t'); --echo # Integer conversions create or replace table t (x tinyint); -if ($have_debug) { ---disable_query_log ---disable_result_log -set debug_dbug= '+d,ib_instant_error'; ---error ER_RECORD_FILE_FULL -alter table t modify x smallint; -set debug_dbug= default; ---enable_query_log ---enable_result_log -} insert into t values (127); alter table t modify x smallint, algorithm=instant; select * from t; @@ -156,6 +133,13 @@ select * from t; check table t extended; call check_table('t'); +if ($have_debug) { +--disable_query_log +# This should not be reachable. +set debug_dbug= @save_debug; +--enable_query_log +} + --echo # Check IMPORT TABLESPACE --let $MYSQLD_DATADIR= `select @@datadir` create or replace table t2 (x int); diff --git a/sql/field.cc b/sql/field.cc index 34f650b8a75..89b04c4d795 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7068,15 +7068,25 @@ uint Field::is_equal(Create_field *new_field) uint Field_str::is_equal(Create_field *new_field) { - if (new_field->type_handler() == type_handler() && - new_field->charset == field_charset) - { - if (new_field->length == max_display_length()) - return IS_EQUAL_YES; - if (new_field->length > max_display_length() && - (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)) - return IS_EQUAL_PACK_LENGTH_EXT; - } + if (new_field->type_handler() != type_handler()) + return IS_EQUAL_NO; + if (new_field->length < max_display_length()) + return IS_EQUAL_NO; + if (new_field->char_length < char_length()) + return IS_EQUAL_NO; + + const bool part_of_a_key= !new_field->field->part_of_key.is_clear_all(); + if (!Type_handler::Charsets_are_compatible(field_charset, new_field->charset, + part_of_a_key)) + return IS_EQUAL_NO; + + if (new_field->length == max_display_length()) + return new_field->charset == field_charset + ? IS_EQUAL_YES : IS_EQUAL_PACK_LENGTH; + + if (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION) + return IS_EQUAL_PACK_LENGTH_EXT; + return IS_EQUAL_NO; } @@ -7915,27 +7925,34 @@ uint Field_varstring::is_equal(Create_field *new_field) { if (new_field->length < field_length) return IS_EQUAL_NO; + if (new_field->char_length < char_length()) + return IS_EQUAL_NO; + if (!new_field->compression_method() != !compression_method()) + return IS_EQUAL_NO; - if (new_field->charset == field_charset && - !new_field->compression_method() == !compression_method()) + bool part_of_a_key= !new_field->field->part_of_key.is_clear_all(); + if (!Type_handler::Charsets_are_compatible(field_charset, new_field->charset, + part_of_a_key)) + return IS_EQUAL_NO; + + const Type_handler *new_type_handler= new_field->type_handler(); + if (new_type_handler == type_handler()) { - const Type_handler *new_type_handler= new_field->type_handler(); - if (new_type_handler == type_handler()) - { - if (new_field->length == field_length) - return IS_EQUAL_YES; - if (field_length <= 127 || - new_field->length <= 255 || - field_length > 255 || - (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)) - return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length - } - else if (new_type_handler == &type_handler_string) // converting to CHAR - { - if (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION) - return IS_EQUAL_PACK_LENGTH_EXT; - } + if (new_field->length == field_length) + return new_field->charset == field_charset + ? IS_EQUAL_YES : IS_EQUAL_PACK_LENGTH; + if (field_length <= 127 || + new_field->length <= 255 || + field_length > 255 || + (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION)) + return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer length } + else if (new_type_handler == &type_handler_string) // converting to CHAR + { + if (table->file->ha_table_flags() & HA_EXTENDED_TYPES_CONVERSION) + return IS_EQUAL_PACK_LENGTH_EXT; + } + return IS_EQUAL_NO; } @@ -8702,10 +8719,32 @@ uint Field_blob::max_packed_col_length(uint max_length) uint Field_blob::is_equal(Create_field *new_field) { - return new_field->type_handler() == type_handler() && - new_field->charset == field_charset && - new_field->pack_length == pack_length() && - !new_field->compression_method() == !compression_method(); + if (new_field->type_handler() != type_handler()) + { + return IS_EQUAL_NO; + } + if (!new_field->compression_method() != !compression_method()) + { + return IS_EQUAL_NO; + } + if (new_field->pack_length != pack_length()) + { + return IS_EQUAL_NO; + } + + bool part_of_a_key= !new_field->field->part_of_key.is_clear_all(); + if (!Type_handler::Charsets_are_compatible(field_charset, new_field->charset, + part_of_a_key)) + { + return IS_EQUAL_NO; + } + + if (field_charset != new_field->charset) + { + return IS_EQUAL_PACK_LENGTH; + } + + return IS_EQUAL_YES; } diff --git a/sql/handler.h b/sql/handler.h index 31abb4699ca..6b9538c7a5d 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -627,6 +627,8 @@ typedef ulonglong alter_table_operations; #define ALTER_KEYS_ONOFF (1ULL << 9) // Set for FORCE, ENGINE(same engine), by mysql_recreate_table() #define ALTER_RECREATE (1ULL << 10) +// Set for CONVERT TO +#define ALTER_CONVERT_TO (1ULL << 11) // Set for ADD FOREIGN KEY #define ALTER_ADD_FOREIGN_KEY (1ULL << 21) // Set for DROP FOREIGN KEY diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 6cccc785fee..1812294ed46 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -8195,3 +8195,49 @@ Type_handler_timestamp_common::Item_param_val_native(THD *thd, item->get_date(thd, <ime, Datetime::Options(TIME_NO_ZERO_IN_DATE, thd)) || TIME_to_native(thd, <ime, to, item->datetime_precision(thd)); } + +static bool charsets_are_compatible(const char *old_cs_name, + const CHARSET_INFO *new_ci) +{ + const char *new_cs_name= new_ci->csname; + + if (!strcmp(old_cs_name, new_cs_name)) + return true; + + if (!strcmp(old_cs_name, MY_UTF8MB3) && !strcmp(new_cs_name, MY_UTF8MB4)) + return true; + + if (!strcmp(old_cs_name, "ascii") && !(new_ci->state & MY_CS_NONASCII)) + return true; + + if (!strcmp(old_cs_name, "ucs2") && !strcmp(new_cs_name, "utf16")) + return true; + + return false; +} + +bool Type_handler::Charsets_are_compatible(const CHARSET_INFO *old_ci, + const CHARSET_INFO *new_ci, + bool part_of_a_key) +{ + const char *old_cs_name= old_ci->csname; + const char *new_cs_name= new_ci->csname; + + if (!charsets_are_compatible(old_cs_name, new_ci)) + { + return false; + } + + if (!part_of_a_key) + { + return true; + } + + if (strcmp(old_ci->name + strlen(old_cs_name), + new_ci->name + strlen(new_cs_name))) + { + return false; + } + + return true; +} diff --git a/sql/sql_type.h b/sql/sql_type.h index d507241075e..7216b24835d 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3672,6 +3672,10 @@ public: virtual bool Vers_history_point_resolve_unit(THD *thd, Vers_history_point *point) const; + + static bool Charsets_are_compatible(const CHARSET_INFO *old_ci, + const CHARSET_INFO *new_ci, + bool part_of_a_key); }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d0b357d3187..0a2961b8154 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8447,7 +8447,7 @@ alter_list_item: $5->name, $4->csname)); if (unlikely(Lex->create_info.add_alter_list_item_convert_to_charset($5))) MYSQL_YYABORT; - Lex->alter_info.flags|= ALTER_OPTIONS; + Lex->alter_info.flags|= ALTER_CONVERT_TO; } | create_table_options_space_separated { diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 4d05767b1be..3bfb8347b13 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -8474,7 +8474,7 @@ alter_list_item: $5->name, $4->csname)); if (unlikely(Lex->create_info.add_alter_list_item_convert_to_charset($5))) MYSQL_YYABORT; - Lex->alter_info.flags|= ALTER_OPTIONS; + Lex->alter_info.flags|= ALTER_CONVERT_TO; } | create_table_options_space_separated { diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 30ca3975bf6..23d2e310b21 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -84,7 +84,6 @@ static const alter_table_operations INNOBASE_ALTER_REBUILD | ALTER_OPTIONS /* ALTER_OPTIONS needs to check alter_options_need_rebuild() */ | ALTER_COLUMN_NULLABLE - | ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT | INNOBASE_DEFAULTS | ALTER_STORED_COLUMN_ORDER | ALTER_DROP_STORED_COLUMN @@ -105,6 +104,7 @@ static const alter_table_operations INNOBASE_INPLACE_IGNORE | ALTER_PARTITIONED | ALTER_COLUMN_COLUMN_FORMAT | ALTER_COLUMN_STORAGE_TYPE + | ALTER_CONVERT_TO | ALTER_VIRTUAL_GCOL_EXPR | ALTER_DROP_CHECK_CONSTRAINT | ALTER_RENAME @@ -135,6 +135,7 @@ static const alter_table_operations INNOBASE_ALTER_INSTANT | ALTER_ADD_VIRTUAL_COLUMN | INNOBASE_FOREIGN_OPERATIONS | ALTER_COLUMN_EQUAL_PACK_LENGTH + | ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT | ALTER_COLUMN_UNVERSIONED | ALTER_DROP_VIRTUAL_COLUMN; @@ -1507,8 +1508,7 @@ instant_alter_column_possible( = ALTER_ADD_STORED_BASE_COLUMN | ALTER_DROP_STORED_COLUMN | ALTER_STORED_COLUMN_ORDER - | ALTER_COLUMN_NULLABLE - | ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT; + | ALTER_COLUMN_NULLABLE; if (!(ha_alter_info->handler_flags & avoid_rebuild)) { alter_table_operations flags = ha_alter_info->handler_flags @@ -1551,7 +1551,6 @@ instant_alter_column_possible( & ~ALTER_STORED_COLUMN_ORDER & ~ALTER_ADD_STORED_BASE_COLUMN & ~ALTER_COLUMN_NULLABLE - & ~ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT & ~ALTER_OPTIONS)) { return false; } @@ -5486,8 +5485,7 @@ static bool innobase_instant_try( trx_t* trx) { DBUG_ASSERT(!ctx->need_rebuild()); - - if (!ctx->is_instant()) return false; + DBUG_ASSERT(ctx->is_instant()); dict_table_t* user_table = ctx->old_table; @@ -8737,7 +8735,6 @@ innobase_drop_foreign_try( @param[in] user_table InnoDB table that was being altered @param[in] trx data dictionary transaction @param[in] table_name Table name in MySQL -@param[in] nth_col 0-based index of the column @param[in] from old column name @param[in] to new column name @param[in] new_clustered whether the table has been rebuilt @@ -8750,7 +8747,6 @@ innobase_rename_column_try( const dict_table_t* user_table, trx_t* trx, const char* table_name, - ulint nth_col, const char* from, const char* to, bool new_clustered) @@ -8770,33 +8766,7 @@ innobase_rename_column_try( } info = pars_info_create(); - - pars_info_add_ull_literal(info, "tableid", user_table->id); - pars_info_add_int4_literal(info, "nth", nth_col); - pars_info_add_str_literal(info, "new", to); - - trx->op_info = "renaming column in SYS_COLUMNS"; - - error = que_eval_sql( - info, - "PROCEDURE RENAME_SYS_COLUMNS_PROC () IS\n" - "BEGIN\n" - "UPDATE SYS_COLUMNS SET NAME=:new\n" - "WHERE TABLE_ID=:tableid\n" - "AND POS=:nth;\n" - "END;\n", - FALSE, trx); - - DBUG_EXECUTE_IF("ib_rename_column_error", - error = DB_OUT_OF_FILE_SPACE;); - - if (error != DB_SUCCESS) { -err_exit: - my_error_innodb(error, table_name, 0); - trx->error_state = DB_SUCCESS; - trx->op_info = ""; - DBUG_RETURN(true); - } + error = DB_SUCCESS; trx->op_info = "renaming column in SYS_FIELDS"; @@ -8839,6 +8809,8 @@ err_exit: "AND POS=:nth;\n" "END;\n", FALSE, trx); + DBUG_EXECUTE_IF("ib_rename_column_error", + error = DB_OUT_OF_FILE_SPACE;); if (error != DB_SUCCESS) { goto err_exit; @@ -8846,6 +8818,14 @@ err_exit: } } + if (error != DB_SUCCESS) { +err_exit: + my_error_innodb(error, table_name, 0); + trx->error_state = DB_SUCCESS; + trx->op_info = ""; + DBUG_RETURN(true); + } + rename_foreign: trx->op_info = "renaming column in SYS_FOREIGN_COLS"; @@ -8968,6 +8948,7 @@ innobase_rename_columns_try( ulint num_v = 0; DBUG_ASSERT(ctx); + DBUG_ASSERT(ctx->need_rebuild()); DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_COLUMN_NAME); @@ -8981,17 +8962,10 @@ innobase_rename_columns_try( cf_it.rewind(); while (Create_field* cf = cf_it++) { if (cf->field == *fp) { - ulint col_n = is_virtual - ? dict_create_v_col_pos( - num_v, i) - : i - num_v; - if (innobase_rename_column_try( ctx->old_table, trx, table_name, - col_n, cf->field->field_name.str, - cf->field_name.str, - ctx->need_rebuild())) { + cf->field_name.str, true)) { return(true); } goto processed_field; @@ -9010,35 +8984,62 @@ processed_field: return(false); } +/** Convert field type and length to InnoDB format */ +static void get_type(const Field& f, ulint& prtype, ulint& mtype, ulint& len) +{ + mtype = get_innobase_type_from_mysql_type(&prtype, &f); + len = f.pack_length(); + prtype |= f.type(); + if (f.type() == MYSQL_TYPE_VARCHAR) { + auto l = static_cast(f).length_bytes; + len -= l; + if (l == 2) prtype |= DATA_LONG_TRUE_VARCHAR; + } + if (!f.real_maybe_null()) prtype |= DATA_NOT_NULL; + if (f.binary()) prtype |= DATA_BINARY_TYPE; + if (f.table->versioned()) { + if (&f == f.table->field[f.table->s->row_start_field]) { + prtype |= DATA_VERS_START; + } else if (&f == f.table->field[f.table->s->row_end_field]) { + prtype |= DATA_VERS_END; + } else if (!(f.flags & VERS_UPDATE_UNVERSIONED_FLAG)) { + prtype |= DATA_VERSIONED; + } + } + if (!f.stored_in_db()) prtype |= DATA_VIRTUAL; + + if (dtype_is_string_type(mtype)) { + prtype |= ulint(f.charset()->number) << 16; + } +} + /** Enlarge a column in the data dictionary tables. @param user_table InnoDB table that was being altered @param trx data dictionary transaction @param table_name Table name in MySQL -@param nth_col 0-based index of the column -@param new_len new column length, in bytes +@param pos 0-based index to user_table->cols[] or user_table->v_cols[] +@param f new column +@param cf column modification @param is_v if it's a virtual column @retval true Failure @retval false Success */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) bool -innobase_enlarge_column_try( -/*========================*/ +innobase_rename_or_enlarge_column_try( const dict_table_t* user_table, trx_t* trx, const char* table_name, - ulint nth_col, - ulint new_len, + ulint pos, + const Field& f, + const Create_field& cf, bool is_v) { - pars_info_t* info; - dberr_t error; #ifdef UNIV_DEBUG dict_col_t* col; #endif /* UNIV_DEBUG */ dict_v_col_t* v_col; - ulint pos; - DBUG_ENTER("innobase_enlarge_column_try"); + DBUG_ENTER("innobase_rename_or_enlarge_column_try"); DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX); ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH); @@ -9046,21 +9047,25 @@ innobase_enlarge_column_try( ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X)); if (is_v) { - v_col = dict_table_get_nth_v_col(user_table, nth_col); + v_col = dict_table_get_nth_v_col(user_table, pos); pos = dict_create_v_col_pos(v_col->v_pos, v_col->m_col.ind); #ifdef UNIV_DEBUG col = &v_col->m_col; #endif /* UNIV_DEBUG */ } else { #ifdef UNIV_DEBUG - col = dict_table_get_nth_col(user_table, nth_col); + col = dict_table_get_nth_col(user_table, pos); #endif /* UNIV_DEBUG */ - pos = nth_col; } + ulint prtype, mtype, len; + get_type(f, prtype, mtype, len); + DBUG_ASSERT(!dtype_is_string_type(col->mtype) + || col->mbminlen == cf.charset->mbminlen); + DBUG_ASSERT(col->len <= len); + #ifdef UNIV_DEBUG - ut_ad(col->len < new_len); - switch (col->mtype) { + switch (mtype) { case DATA_FIXBINARY: case DATA_CHAR: case DATA_MYSQL: @@ -9068,120 +9073,124 @@ innobase_enlarge_column_try( and ROW_FORMAT is not REDUNDANT and mbminlennot_redundant()) { - ut_error; - } + ut_ad(!user_table->not_redundant() || col->len == len); + break; case DATA_BINARY: case DATA_VARCHAR: case DATA_VARMYSQL: case DATA_DECIMAL: case DATA_BLOB: break; + case DATA_INT: + if (!user_table->not_redundant()) { + break; + } + /* fall through */ default: - ut_error; + ut_ad(col->prtype == prtype); + ut_ad(col->mtype == mtype); + ut_ad(col->len == len); } #endif /* UNIV_DEBUG */ - info = pars_info_create(); - pars_info_add_ull_literal(info, "tableid", user_table->id); - pars_info_add_int4_literal(info, "nth", pos); - pars_info_add_int4_literal(info, "new", new_len); + const char* col_name = col->name(*user_table); + const bool same_name = !strcmp(col_name, f.field_name.str); - trx->op_info = "resizing column in SYS_COLUMNS"; - - error = que_eval_sql( - info, - "PROCEDURE RESIZE_SYS_COLUMNS_PROC () IS\n" - "BEGIN\n" - "UPDATE SYS_COLUMNS SET LEN=:new\n" - "WHERE TABLE_ID=:tableid AND POS=:nth;\n" - "END;\n", - FALSE, trx); - - DBUG_EXECUTE_IF("ib_resize_column_error", - error = DB_OUT_OF_FILE_SPACE;); - - trx->op_info = ""; - trx->error_state = DB_SUCCESS; - - if (error != DB_SUCCESS) { - my_error_innodb(error, table_name, 0); + if (!same_name + && innobase_rename_column_try(user_table, trx, table_name, + col_name, f.field_name.str, + false)) { DBUG_RETURN(true); } - DBUG_RETURN(false); + if (same_name + && col->prtype == prtype && col->mtype == mtype + && col->len == len) { + DBUG_RETURN(false); + } + + DBUG_RETURN(innodb_insert_sys_columns(user_table->id, pos, + f.field_name.str, + mtype, prtype, len, + is_v ? v_col->num_base : 0, + trx, true)); } -/** Enlarge columns in the data dictionary tables. +/** Rename or enlarge columns in the data dictionary cache +as part of commit_try_norebuild(). @param ha_alter_info Data used during in-place alter. -@param table the TABLE -@param user_table InnoDB table that was being altered +@param ctx In-place ALTER TABLE context +@param altered_table metadata after ALTER TABLE +@param table metadata before ALTER TABLE @param trx data dictionary transaction @param table_name Table name in MySQL @retval true Failure @retval false Success */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) bool -innobase_enlarge_columns_try( -/*=========================*/ +innobase_rename_or_enlarge_columns_try( Alter_inplace_info* ha_alter_info, + ha_innobase_inplace_ctx*ctx, + const TABLE* altered_table, const TABLE* table, - const dict_table_t* user_table, trx_t* trx, const char* table_name) { + DBUG_ENTER("innobase_rename_or_enlarge_columns_try"); + DBUG_ASSERT(ctx); + + if (!(ha_alter_info->handler_flags + & (ALTER_COLUMN_EQUAL_PACK_LENGTH + | ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT + | ALTER_COLUMN_NAME))) { + DBUG_RETURN(false); + } + List_iterator_fast cf_it( ha_alter_info->alter_info->create_list); ulint i = 0; ulint num_v = 0; - bool is_v; for (Field** fp = table->field; *fp; fp++, i++) { - ulint idx; - - if (innobase_is_v_fld(*fp)) { - is_v = true; - idx = num_v; - num_v++; - } else { - idx = i - num_v; - is_v = false; - } + const bool is_v = !(*fp)->stored_in_db(); + ulint idx = is_v ? num_v++ : i - num_v; cf_it.rewind(); + Field** af = altered_table->field; while (Create_field* cf = cf_it++) { if (cf->field == *fp) { - if ((*fp)->is_equal(cf) - == IS_EQUAL_PACK_LENGTH - && innobase_enlarge_column_try( - user_table, trx, table_name, - idx, static_cast(cf->length), is_v)) { - return(true); + if (innobase_rename_or_enlarge_column_try( + ctx->old_table, trx, table_name, + idx, **af, *cf, is_v)) { + DBUG_RETURN(true); } - break; } + af++; } } - return(false); + DBUG_RETURN(false); } /** Rename or enlarge columns in the data dictionary cache as part of commit_cache_norebuild(). @param ha_alter_info Data used during in-place alter. -@param table the TABLE +@param altered_table metadata after ALTER TABLE +@param table metadata before ALTER TABLE @param user_table InnoDB table that was being altered */ static MY_ATTRIBUTE((nonnull)) void innobase_rename_or_enlarge_columns_cache( /*=====================================*/ Alter_inplace_info* ha_alter_info, + const TABLE* altered_table, const TABLE* table, dict_table_t* user_table) { if (!(ha_alter_info->handler_flags & (ALTER_COLUMN_EQUAL_PACK_LENGTH + | ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT | ALTER_COLUMN_NAME))) { return; } @@ -9195,26 +9204,33 @@ innobase_rename_or_enlarge_columns_cache( bool is_virtual = innobase_is_v_fld(*fp); cf_it.rewind(); + Field** af = altered_table->field; while (Create_field* cf = cf_it++) { if (cf->field != *fp) { + af++; continue; } ulint col_n = is_virtual ? num_v : i - num_v; + dict_col_t *col = is_virtual + ? &dict_table_get_nth_v_col(user_table, col_n) + ->m_col + : dict_table_get_nth_col(user_table, col_n); + const bool is_string= dtype_is_string_type(col->mtype); + DBUG_ASSERT(!is_string + || (*af)->charset() == cf->charset); + DBUG_ASSERT(col->mbminlen + == (is_string + ? (*af)->charset()->mbminlen : 0)); + ulint prtype, mtype, len; + get_type(**af, prtype, mtype, len); + DBUG_ASSERT(is_string == dtype_is_string_type(mtype)); - if ((*fp)->is_equal(cf) == IS_EQUAL_PACK_LENGTH) { - dict_col_t *col = is_virtual ? - &dict_table_get_nth_v_col( - user_table, col_n)->m_col - : dict_table_get_nth_col( - user_table, col_n); - col->len = cf->length; - if (col->len > 255 - && (col->prtype & DATA_MYSQL_TRUE_VARCHAR) - == DATA_MYSQL_TRUE_VARCHAR) { - col->prtype |= DATA_LONG_TRUE_VARCHAR; - } - } + col->prtype = prtype; + col->mtype = mtype; + col->len = len; + col->mbmaxlen = is_string + ? (*af)->charset()->mbmaxlen : 0; if ((*fp)->flags & FIELD_IS_RENAMED) { dict_mem_table_col_rename( @@ -10126,17 +10142,9 @@ commit_try_norebuild( } } - if ((ha_alter_info->handler_flags - & ALTER_COLUMN_NAME) - && innobase_rename_columns_try(ha_alter_info, ctx, old_table, - trx, table_name)) { - DBUG_RETURN(true); - } - - if ((ha_alter_info->handler_flags - & ALTER_COLUMN_EQUAL_PACK_LENGTH) - && innobase_enlarge_columns_try(ha_alter_info, old_table, - ctx->old_table, trx, table_name)) { + if (innobase_rename_or_enlarge_columns_try(ha_alter_info, ctx, + altered_table, old_table, + trx, table_name)) { DBUG_RETURN(true); } @@ -10148,7 +10156,13 @@ commit_try_norebuild( } #endif /* MYSQL_RENAME_INDEX */ - if (!ctx->is_instant() && ha_alter_info->handler_flags + if (ctx->is_instant()) { + DBUG_RETURN(innobase_instant_try(ha_alter_info, ctx, + altered_table, old_table, + trx)); + } + + if (ha_alter_info->handler_flags & (ALTER_DROP_VIRTUAL_COLUMN | ALTER_ADD_VIRTUAL_COLUMN)) { if ((ha_alter_info->handler_flags & ALTER_DROP_VIRTUAL_COLUMN) && innobase_drop_virtual_try(ha_alter_info, ctx->old_table, @@ -10176,14 +10190,14 @@ commit_try_norebuild( } } - DBUG_RETURN(innobase_instant_try(ha_alter_info, ctx, altered_table, - old_table, trx)); + DBUG_RETURN(false); } /** Commit the changes to the data dictionary cache after a successful commit_try_norebuild() call. @param ha_alter_info algorithm=inplace context @param ctx In-place ALTER TABLE context for the current partition +@param altered_table the TABLE after the ALTER @param table the TABLE before the ALTER @param trx Data dictionary transaction (will be started and committed, for DROP INDEX) */ @@ -10193,6 +10207,7 @@ commit_cache_norebuild( /*===================*/ Alter_inplace_info* ha_alter_info, ha_innobase_inplace_ctx*ctx, + const TABLE* altered_table, const TABLE* table, trx_t* trx) { @@ -10337,7 +10352,7 @@ commit_cache_norebuild( if (!ctx->is_instant()) { innobase_rename_or_enlarge_columns_cache( - ha_alter_info, table, ctx->new_table); + ha_alter_info, altered_table, table, ctx->new_table); } else { ut_ad(ctx->col_map); @@ -11019,6 +11034,7 @@ foreign_fail: " key constraints."); } else { commit_cache_norebuild(ha_alter_info, ctx, + altered_table, table, trx); } } From 282ba973e748456a829eecf1b49fb352870c6a8f Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 14 Feb 2019 20:18:34 +0100 Subject: [PATCH 91/91] MDEV-18549 Failing assertion: opt_no_lock during mariabackup --backup The assertion happens under BACKUP STAGE BLOCK_COMMIT, when a DDL on a temporary table (#sql-xxx) is found. Apparently, assumption that all DDLs are blocked under FTWRL does not hold for BACKUP STAGE, and temporary tables can still have ALTERs The fix is to relax the assertion, and only check for opt_no_lock if backup is *really* inconsistent, i.e either optimized DDL or CREATE/RENAME are done on the tables that were not skipped during backup. --- extra/mariabackup/xtrabackup.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 8a107a408eb..60df902e098 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -644,7 +644,6 @@ static void backup_file_op_fail(ulint space_id, const byte* flags, const byte* name, ulint len, const byte* new_name, ulint new_len) { - ut_a(opt_no_lock); bool fail; if (flags) { msg("DDL tracking : create %zu \"%.*s\": %x", @@ -665,6 +664,7 @@ static void backup_file_op_fail(ulint space_id, const byte* flags, msg("DDL tracking : delete %zu \"%.*s\"", space_id, int(len), name); } if (fail) { + ut_a(opt_no_lock); die("DDL operation detected in the late phase of backup." "Backup is inconsistent. Remove --no-lock option to fix."); } @@ -685,9 +685,9 @@ static void backup_optimized_ddl_op(ulint space_id) run with --no-lock. Usually aborts the backup. */ static void backup_optimized_ddl_op_fail(ulint space_id) { - ut_a(opt_no_lock); msg("DDL tracking : optimized DDL on space %zu", space_id); if (ddl_tracker.tables_in_backup.find(space_id) != ddl_tracker.tables_in_backup.end()) { + ut_a(opt_no_lock); msg("ERROR : Optimized DDL operation detected in the late phase of backup." "Backup is inconsistent. Remove --no-lock option to fix."); exit(EXIT_FAILURE);