summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2021-03-05 12:54:43 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2021-03-05 12:54:43 +0200
commit10d544aa7b305210246a976ca47a7559f8b78f72 (patch)
treea6df2319a67afbc523be05789c77e9a28a49e29c
parentaa4f76bed715ec1016260f593e9cf4a8a1a4da36 (diff)
parentfcc9f8b10cd2f497ff410b592808eedb3ee5f212 (diff)
downloadmariadb-git-10d544aa7b305210246a976ca47a7559f8b78f72.tar.gz
Merge 10.4 into 10.5
-rw-r--r--include/my_base.h6
-rw-r--r--mysql-test/lib/My/Debugger.pm3
-rw-r--r--mysql-test/main/flush_and_binlog.result11
-rw-r--r--mysql-test/main/flush_and_binlog.test14
-rw-r--r--mysql-test/main/group_by.result29
-rw-r--r--mysql-test/main/group_by.test23
-rw-r--r--mysql-test/main/having.result33
-rw-r--r--mysql-test/main/having.test21
-rw-r--r--mysql-test/main/ps.result17
-rw-r--r--mysql-test/main/ps.test14
-rw-r--r--mysql-test/main/set_statement.result26
-rw-r--r--mysql-test/main/set_statement.test26
-rw-r--r--mysql-test/main/table_value_constr.result6
-rw-r--r--mysql-test/main/table_value_constr.test6
-rwxr-xr-xmysql-test/mysql-test-run.pl2
-rw-r--r--mysql-test/suite/innodb/r/truncate_foreign.result11
-rw-r--r--mysql-test/suite/innodb/t/truncate_foreign.test13
-rw-r--r--mysql-test/suite/plugins/r/server_audit.result3
-rw-r--r--mysql-test/suite/plugins/t/server_audit.test1
-rw-r--r--mysql-test/suite/unit/suite.pm11
-rw-r--r--mysys/file_logger.c55
-rw-r--r--plugin/server_audit/server_audit.c107
-rw-r--r--sql/ha_partition.cc1
-rw-r--r--sql/handler.h6
-rw-r--r--sql/item.cc53
-rw-r--r--sql/item.h15
-rw-r--r--sql/sql_admin.cc2
-rw-r--r--sql/sql_parse.cc268
-rw-r--r--sql/sql_parse.h1
-rw-r--r--sql/sql_prepare.cc16
-rw-r--r--sql/sql_select.cc129
-rw-r--r--sql/sql_truncate.cc9
-rw-r--r--sql/sql_tvc.cc15
-rw-r--r--sql/table.h6
-rw-r--r--storage/innobase/handler/ha_innodb.cc10
-rw-r--r--storage/innobase/lock/lock0lock.cc31
-rw-r--r--storage/innobase/trx/trx0trx.cc41
-rw-r--r--storage/maria/ma_recovery.c1
-rw-r--r--storage/maria/ma_recovery_util.c1
-rw-r--r--storage/mroonga/ha_mroonga.cpp3
40 files changed, 771 insertions, 275 deletions
diff --git a/include/my_base.h b/include/my_base.h
index dc5b135628f..6a9a14fa91e 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
- Copyright (c) 1995, 2018, MariaDB Corporation.
+ Copyright (c) 1995, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -217,9 +217,7 @@ enum ha_extra_function {
/** Start writing rows during ALTER TABLE...ALGORITHM=COPY. */
HA_EXTRA_BEGIN_ALTER_COPY,
/** Finish writing rows during ALTER TABLE...ALGORITHM=COPY. */
- HA_EXTRA_END_ALTER_COPY,
- /** Fake the start of a statement after wsrep_load_data_splitting hack */
- HA_EXTRA_FAKE_START_STMT
+ HA_EXTRA_END_ALTER_COPY
};
/* Compatible option, to be deleted in 6.0 */
diff --git a/mysql-test/lib/My/Debugger.pm b/mysql-test/lib/My/Debugger.pm
index 2bbffc89f1a..0854a1c4363 100644
--- a/mysql-test/lib/My/Debugger.pm
+++ b/mysql-test/lib/My/Debugger.pm
@@ -74,7 +74,8 @@ my %debuggers = (
options => '-f -o {log} {exe} {args}',
},
rr => {
- options => 'record -o {log} {exe} {args}',
+ options => '_RR_TRACE_DIR={log} rr record {exe} {args}',
+ run => 'env',
pre => sub {
::mtr_error('rr requires kernel.perf_event_paranoid <= 1')
if ::mtr_grab_file('/proc/sys/kernel/perf_event_paranoid') > 1;
diff --git a/mysql-test/main/flush_and_binlog.result b/mysql-test/main/flush_and_binlog.result
index b9560964046..a1d73c6590f 100644
--- a/mysql-test/main/flush_and_binlog.result
+++ b/mysql-test/main/flush_and_binlog.result
@@ -20,3 +20,14 @@ ERROR HY000: Lock wait timeout exceeded; try restarting transaction
connection default;
disconnect con1;
unlock tables;
+# Second test from MDEV-23843
+CREATE TABLE t (a INT);
+FLUSH TABLES WITH READ LOCK;
+connect con1,localhost,root,,;
+SET lock_wait_timeout= 1;
+ANALYZE TABLE t;
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+disconnect con1;
+connection default;
+UNLOCK TABLES;
+DROP TABLE t;
diff --git a/mysql-test/main/flush_and_binlog.test b/mysql-test/main/flush_and_binlog.test
index 373b900b451..a28d8e365dd 100644
--- a/mysql-test/main/flush_and_binlog.test
+++ b/mysql-test/main/flush_and_binlog.test
@@ -27,3 +27,17 @@ FLUSH TABLES;
--connection default
--disconnect con1
unlock tables;
+
+--echo # Second test from MDEV-23843
+
+CREATE TABLE t (a INT);
+FLUSH TABLES WITH READ LOCK;
+--connect (con1,localhost,root,,)
+SET lock_wait_timeout= 1;
+--error ER_LOCK_WAIT_TIMEOUT
+ANALYZE TABLE t;
+# Cleanup
+--disconnect con1
+--connection default
+UNLOCK TABLES;
+DROP TABLE t;
diff --git a/mysql-test/main/group_by.result b/mysql-test/main/group_by.result
index 54a9da479dd..8c1ba102e8f 100644
--- a/mysql-test/main/group_by.result
+++ b/mysql-test/main/group_by.result
@@ -2958,5 +2958,34 @@ f COUNT(*)
NULL 1
DROP TABLE t1;
#
+# MDEV-24710 Uninitialized value upon CREATE .. SELECT ... VALUE
+#
+CREATE TABLE t1 (a VARCHAR(8) NOT NULL DEFAULT '');
+INSERT INTO t1 (a) VALUES ('foo');
+CREATE TABLE t2 AS SELECT MAX(a) AS f1, a AS f2 FROM t1 WHERE VALUE(a) IS NOT NULL;
+SELECT * from t2;
+f1 f2
+NULL NULL
+SELECT MAX(a) AS f1, a AS f2 FROM t1 WHERE VALUE(a) IS NOT NULL;
+f1 f2
+NULL NULL
+SELECT MAX(a) AS f1, a AS f2 FROM t1 WHERE 1=0;
+f1 f2
+NULL NULL
+drop table t1,t2;
+# Extra test by to check the fix for MDEV-24710
+create table t20 (pk int primary key, a int);
+insert into t20 values (1,1);
+create table t21 (pk int primary key, b int not null);
+insert into t21 values (1,1);
+create table t22 (a int);
+insert into t22 values (1),(2);
+select a, (select max(t21.b) from t20 left join t21 on t21.pk=t20.a+10
+where t20.pk=1 and rand(123) < 0.5) as SUBQ from t22;
+a SUBQ
+1 NULL
+2 NULL
+drop table t20, t21, t22;
+#
# End of 10.3 tests
#
diff --git a/mysql-test/main/group_by.test b/mysql-test/main/group_by.test
index d5908946afa..97209b50cda 100644
--- a/mysql-test/main/group_by.test
+++ b/mysql-test/main/group_by.test
@@ -2062,5 +2062,28 @@ SELECT d != '2023-03-04' AS f, COUNT(*) FROM t1 GROUP BY d WITH ROLLUP;
DROP TABLE t1;
--echo #
+--echo # MDEV-24710 Uninitialized value upon CREATE .. SELECT ... VALUE
+--echo #
+
+CREATE TABLE t1 (a VARCHAR(8) NOT NULL DEFAULT '');
+INSERT INTO t1 (a) VALUES ('foo');
+CREATE TABLE t2 AS SELECT MAX(a) AS f1, a AS f2 FROM t1 WHERE VALUE(a) IS NOT NULL;
+SELECT * from t2;
+SELECT MAX(a) AS f1, a AS f2 FROM t1 WHERE VALUE(a) IS NOT NULL;
+SELECT MAX(a) AS f1, a AS f2 FROM t1 WHERE 1=0;
+drop table t1,t2;
+
+--echo # Extra test by to check the fix for MDEV-24710
+
+create table t20 (pk int primary key, a int);
+insert into t20 values (1,1);create table t21 (pk int primary key, b int not null);
+insert into t21 values (1,1);
+create table t22 (a int);
+insert into t22 values (1),(2);
+select a, (select max(t21.b) from t20 left join t21 on t21.pk=t20.a+10
+ where t20.pk=1 and rand(123) < 0.5) as SUBQ from t22;
+drop table t20, t21, t22;
+
+--echo #
--echo # End of 10.3 tests
--echo #
diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result
index 703f013c2da..51b88c5b8d2 100644
--- a/mysql-test/main/having.result
+++ b/mysql-test/main/having.result
@@ -847,6 +847,39 @@ t r
DROP TABLE t1;
DROP FUNCTION next_seq_value;
DROP TABLE series;
+#
+# MDEV-24958 Server crashes in my_strtod /
+# Value_source::Converter_strntod::Converter_strntod with DEFAULT(blob)
+#
+# MDEV-24942 Server crashes in _ma_rec_pack / _ma_write_blob_record with
+# DEFAULT() on BLOB
+#
+CREATE TABLE t1 (id INT, f MEDIUMTEXT NOT NULL DEFAULT 'A');
+INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
+SELECT f FROM t1 GROUP BY id ORDER BY DEFAULT(f);
+f
+foo
+bar
+SELECT DEFAULT(f) AS h FROM t1 HAVING h > 5;
+h
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'A'
+SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 0;
+h
+A
+A
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'A'
+SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 'A';
+h
+A
+A
+alter table t1 add column b int default (rand()+1+3);
+select default(b) AS h FROM t1 HAVING h > "2";
+h
+#
+#
+drop table t1;
# End of 10.3 tests
#
# MDEV-18681: AND formula in HAVING with several occurances
diff --git a/mysql-test/main/having.test b/mysql-test/main/having.test
index 072f1a088dc..7e0a0439f8e 100644
--- a/mysql-test/main/having.test
+++ b/mysql-test/main/having.test
@@ -891,6 +891,27 @@ DROP TABLE t1;
DROP FUNCTION next_seq_value;
DROP TABLE series;
+
+--echo #
+--echo # MDEV-24958 Server crashes in my_strtod /
+--echo # Value_source::Converter_strntod::Converter_strntod with DEFAULT(blob)
+--echo #
+--echo # MDEV-24942 Server crashes in _ma_rec_pack / _ma_write_blob_record with
+--echo # DEFAULT() on BLOB
+--echo #
+
+CREATE TABLE t1 (id INT, f MEDIUMTEXT NOT NULL DEFAULT 'A');
+INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
+SELECT f FROM t1 GROUP BY id ORDER BY DEFAULT(f);
+SELECT DEFAULT(f) AS h FROM t1 HAVING h > 5;
+SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 0;
+SELECT DEFAULT(f) AS h FROM t1 HAVING h >= 'A';
+
+alter table t1 add column b int default (rand()+1+3);
+--replace_column 1 #
+select default(b) AS h FROM t1 HAVING h > "2";
+drop table t1;
+
--echo # End of 10.3 tests
--echo #
diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result
index b7e126e5061..1c13b0a0b84 100644
--- a/mysql-test/main/ps.result
+++ b/mysql-test/main/ps.result
@@ -5497,6 +5497,23 @@ EXISTS(SELECT 1 FROM t1 GROUP BY a IN (select a from t1))
0
DROP TABLE t1;
#
+# MDEV-25006: Failed assertion on executing EXPLAIN DELETE statement as a prepared statement
+#
+CREATE TABLE t1(c1 CHAR(255) PRIMARY KEY);
+PREPARE stmt FROM 'EXPLAIN DELETE b FROM t1 AS a JOIN t1 AS b';
+EXECUTE stmt;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE a system NULL NULL NULL NULL 0 Const row not found
+1 SIMPLE b system NULL NULL NULL NULL 0 Const row not found
+DROP TABLE t1;
+CREATE TABLE t1(a INT);
+PREPARE stmt FROM 'EXPLAIN DELETE FROM t1.* USING t1';
+EXECUTE stmt;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 0 Const row not found
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+#
# End of 10.2 tests
#
#
diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test
index 6a109951d0e..2ce78b78e90 100644
--- a/mysql-test/main/ps.test
+++ b/mysql-test/main/ps.test
@@ -4942,6 +4942,20 @@ EXECUTE stmt;
DROP TABLE t1;
--echo #
+--echo # MDEV-25006: Failed assertion on executing EXPLAIN DELETE statement as a prepared statement
+--echo #
+
+CREATE TABLE t1(c1 CHAR(255) PRIMARY KEY);
+PREPARE stmt FROM 'EXPLAIN DELETE b FROM t1 AS a JOIN t1 AS b';
+EXECUTE stmt;
+DROP TABLE t1;
+CREATE TABLE t1(a INT);
+PREPARE stmt FROM 'EXPLAIN DELETE FROM t1.* USING t1';
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+DROP TABLE t1;
+
+--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/mysql-test/main/set_statement.result b/mysql-test/main/set_statement.result
index 511ecf77357..53574fb4e4f 100644
--- a/mysql-test/main/set_statement.result
+++ b/mysql-test/main/set_statement.result
@@ -1217,6 +1217,31 @@ set @rnd=1;
select @rnd;
@rnd
0
+#
+# MDEV-24860: Incorrect behaviour of SET STATEMENT in case
+# it is executed as a prepared statement
+#
+PREPARE stmt FROM "SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR CREATE TABLE t1 AS SELECT CONCAT('abc') AS c1";
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+# Show definition of the table t1 created using Prepared Statement
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` varchar(3) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+# Create the table t1 with the same definition as it used before
+# using regular statement execution mode.
+SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR CREATE TABLE t1 AS SELECT CONCAT('abc') AS c1;
+# Show that the table has the same definition as it is in case the table
+# created in prepared statement mode.
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` varchar(3) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
create table t (a int);
SET sql_mode=ORACLE;
SET STATEMENT myisam_sort_buffer_size=800000 FOR OPTIMIZE TABLE t;
@@ -1234,3 +1259,4 @@ SET sql_mode=ORACLE;
SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown';
SET sql_mode=default;
SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown';
+# End of 10.4 tests
diff --git a/mysql-test/main/set_statement.test b/mysql-test/main/set_statement.test
index 12a6ccad8f9..670e9862abc 100644
--- a/mysql-test/main/set_statement.test
+++ b/mysql-test/main/set_statement.test
@@ -1137,6 +1137,30 @@ while ($1)
--echo # @rnd should be 0
select @rnd;
+
+--echo #
+--echo # MDEV-24860: Incorrect behaviour of SET STATEMENT in case
+--echo # it is executed as a prepared statement
+--echo #
+PREPARE stmt FROM "SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR CREATE TABLE t1 AS SELECT CONCAT('abc') AS c1";
+EXECUTE stmt;
+DEALLOCATE PREPARE stmt;
+
+--echo # Show definition of the table t1 created using Prepared Statement
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
+
+--echo # Create the table t1 with the same definition as it used before
+--echo # using regular statement execution mode.
+SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR CREATE TABLE t1 AS SELECT CONCAT('abc') AS c1;
+
+--echo # Show that the table has the same definition as it is in case the table
+--echo # created in prepared statement mode.
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
+
create table t (a int);
SET sql_mode=ORACLE;
SET STATEMENT myisam_sort_buffer_size=800000 FOR OPTIMIZE TABLE t;
@@ -1152,3 +1176,5 @@ SET sql_mode=ORACLE;
SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown';
SET sql_mode=default;
SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown';
+
+--echo # End of 10.4 tests
diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result
index 3bb27589f66..01eee420885 100644
--- a/mysql-test/main/table_value_constr.result
+++ b/mysql-test/main/table_value_constr.result
@@ -2880,8 +2880,12 @@ deallocate prepare stmt;
drop view v1;
drop table t1,t2,t3;
#
-# End of 10.3 tests
+# MDEV-24919: subselect formed by TVC and used in set function
#
+select sum((values(1)));
+sum((values(1)))
+1
+End of 10.3 tests
#
# MDEV-22610 Crash in INSERT INTO t1 (VALUES (DEFAULT) UNION VALUES (DEFAULT))
#
diff --git a/mysql-test/main/table_value_constr.test b/mysql-test/main/table_value_constr.test
index d2baccd1e7e..0e0e102a29c 100644
--- a/mysql-test/main/table_value_constr.test
+++ b/mysql-test/main/table_value_constr.test
@@ -1517,9 +1517,13 @@ drop view v1;
drop table t1,t2,t3;
--echo #
---echo # End of 10.3 tests
+--echo # MDEV-24919: subselect formed by TVC and used in set function
--echo #
+select sum((values(1)));
+
+--echo End of 10.3 tests
+
--echo #
--echo # MDEV-22610 Crash in INSERT INTO t1 (VALUES (DEFAULT) UNION VALUES (DEFAULT))
--echo #
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index f8b349f3239..fd0e5ffd12a 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -5000,7 +5000,7 @@ sub mysqld_start ($$) {
$ENV{'MYSQLD_LAST_CMD'}= "$exe @$args";
My::Debugger::setup_args(\$args, \$exe, $mysqld->name());
- $ENV{'VALGRIND_TEST'}= $opt_valgrind = int($exe && $exe eq 'valgrind');
+ $ENV{'VALGRIND_TEST'}= $opt_valgrind = int(($exe || '') eq 'valgrind');
# Remove the old pidfile if any
unlink($mysqld->value('pid-file'));
diff --git a/mysql-test/suite/innodb/r/truncate_foreign.result b/mysql-test/suite/innodb/r/truncate_foreign.result
index fc09b74d62f..12a41860708 100644
--- a/mysql-test/suite/innodb/r/truncate_foreign.result
+++ b/mysql-test/suite/innodb/r/truncate_foreign.result
@@ -57,3 +57,14 @@ disconnect dml;
connection default;
SET DEBUG_SYNC = RESET;
DROP TABLE child, parent;
+#
+# MDEV-24532 Table corruption ER_NO_SUCH_TABLE_IN_ENGINE or
+# ER_CRASHED_ON_USAGE after ALTER on table with foreign key
+#
+CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a)) ENGINE=InnoDB;
+ALTER TABLE t1 ADD FOREIGN KEY (b) REFERENCES t1 (a) ON UPDATE CASCADE;
+LOCK TABLE t1 WRITE;
+TRUNCATE TABLE t1;
+ALTER TABLE t1 ADD c INT;
+UNLOCK TABLES;
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/t/truncate_foreign.test b/mysql-test/suite/innodb/t/truncate_foreign.test
index d9d647e69f0..1c150e5db40 100644
--- a/mysql-test/suite/innodb/t/truncate_foreign.test
+++ b/mysql-test/suite/innodb/t/truncate_foreign.test
@@ -67,3 +67,16 @@ connection default;
SET DEBUG_SYNC = RESET;
DROP TABLE child, parent;
+
+--echo #
+--echo # MDEV-24532 Table corruption ER_NO_SUCH_TABLE_IN_ENGINE or
+--echo # ER_CRASHED_ON_USAGE after ALTER on table with foreign key
+--echo #
+
+CREATE TABLE t1 (a INT, b INT, PRIMARY KEY (a)) ENGINE=InnoDB;
+ALTER TABLE t1 ADD FOREIGN KEY (b) REFERENCES t1 (a) ON UPDATE CASCADE;
+LOCK TABLE t1 WRITE;
+TRUNCATE TABLE t1;
+ALTER TABLE t1 ADD c INT;
+UNLOCK TABLES;
+DROP TABLE t1;
diff --git a/mysql-test/suite/plugins/r/server_audit.result b/mysql-test/suite/plugins/r/server_audit.result
index 2c06b70c509..ac710a7ab85 100644
--- a/mysql-test/suite/plugins/r/server_audit.result
+++ b/mysql-test/suite/plugins/r/server_audit.result
@@ -118,6 +118,7 @@ CREATE USER u1 IDENTIFIED BY 'pwd-123';
GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321";
SET PASSWORD FOR u1 = PASSWORD('pwd 098');
CREATE USER u3 IDENTIFIED BY '';
+ALTER USER u3 IDENTIFIED BY 'pwd-456';
drop user u1, u2, u3;
set global server_audit_events='query_ddl';
create table t1(id int);
@@ -393,6 +394,8 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,proxies_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,roles_mapping,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv,
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0
+TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv,
+TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'ALTER USER u3 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,db,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv,
diff --git a/mysql-test/suite/plugins/t/server_audit.test b/mysql-test/suite/plugins/t/server_audit.test
index 0d65c451d08..8edf898a998 100644
--- a/mysql-test/suite/plugins/t/server_audit.test
+++ b/mysql-test/suite/plugins/t/server_audit.test
@@ -95,6 +95,7 @@ CREATE USER u1 IDENTIFIED BY 'pwd-123';
GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321";
SET PASSWORD FOR u1 = PASSWORD('pwd 098');
CREATE USER u3 IDENTIFIED BY '';
+ALTER USER u3 IDENTIFIED BY 'pwd-456';
drop user u1, u2, u3;
set global server_audit_events='query_ddl';
diff --git a/mysql-test/suite/unit/suite.pm b/mysql-test/suite/unit/suite.pm
index b7a1f9ae871..43c9e115de6 100644
--- a/mysql-test/suite/unit/suite.pm
+++ b/mysql-test/suite/unit/suite.pm
@@ -20,7 +20,6 @@ sub start_test {
($path, $args) = ($cmd, , [ ])
}
-
my $oldpwd=getcwd();
chdir $::opt_vardir;
my $proc=My::SafeProcess->new
@@ -49,12 +48,12 @@ sub start_test {
my ($command, %tests, $prefix);
for (@ctest_list) {
chomp;
- if (/^\d+: Test command: +/) {
- $command= $';
+ if (/^\d+: Test command: +([^ \t]+)/) {
+ $command= $1;
$prefix= /libmariadb/ ? 'conc_' : '';
- } elsif (/^ +Test +#\d+: +/) {
- if ($command ne "NOT_AVAILABLE") {
- $tests{$prefix.$'}=$command;
+ } elsif (/^ +Test +#\d+: ([^ \t]+)/) {
+ if ($command ne "NOT_AVAILABLE" && $command ne "/bin/sh") {
+ $tests{$prefix.$1}=$command;
}
}
}
diff --git a/mysys/file_logger.c b/mysys/file_logger.c
index eb5579fb8a9..a753c049f68 100644
--- a/mysys/file_logger.c
+++ b/mysys/file_logger.c
@@ -151,23 +151,34 @@ exit:
}
+/*
+ Return 1 if we should rotate the log
+*/
+
+my_bool logger_time_to_rotate(LOGGER_HANDLE *log)
+{
+ my_off_t filesize;
+ if (log->rotations > 0 &&
+ (filesize= my_tell(log->file, MYF(0))) != (my_off_t) -1 &&
+ ((ulonglong) filesize >= log->size_limit))
+ return 1;
+ return 0;
+}
+
+
int logger_vprintf(LOGGER_HANDLE *log, const char* fmt, va_list ap)
{
int result;
- my_off_t filesize;
char cvtbuf[1024];
size_t n_bytes;
flogger_mutex_lock(&log->lock);
- if (log->rotations > 0)
- if ((filesize= my_tell(log->file, MYF(0))) == (my_off_t) -1 ||
- ((unsigned long long)filesize >= log->size_limit &&
- do_rotate(log)))
- {
- result= -1;
- errno= my_errno;
- goto exit; /* Log rotation needed but failed */
- }
+ if (logger_time_to_rotate(log) && do_rotate(log))
+ {
+ result= -1;
+ errno= my_errno;
+ goto exit; /* Log rotation needed but failed */
+ }
n_bytes= my_vsnprintf(cvtbuf, sizeof(cvtbuf), fmt, ap);
if (n_bytes >= sizeof(cvtbuf))
@@ -181,21 +192,18 @@ exit:
}
-int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size)
+static int logger_write_r(LOGGER_HANDLE *log, my_bool allow_rotations,
+ const char *buffer, size_t size)
{
int result;
- my_off_t filesize;
flogger_mutex_lock(&log->lock);
- if (log->rotations > 0)
- if ((filesize= my_tell(log->file, MYF(0))) == (my_off_t) -1 ||
- ((unsigned long long)filesize >= log->size_limit &&
- do_rotate(log)))
- {
- result= -1;
- errno= my_errno;
- goto exit; /* Log rotation needed but failed */
- }
+ if (allow_rotations && logger_time_to_rotate(log) && do_rotate(log))
+ {
+ result= -1;
+ errno= my_errno;
+ goto exit; /* Log rotation needed but failed */
+ }
result= (int)my_write(log->file, (uchar *) buffer, size, MYF(0));
@@ -205,6 +213,11 @@ exit:
}
+int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size)
+{
+ return logger_write_r(log, TRUE, buffer, size);
+}
+
int logger_rotate(LOGGER_HANDLE *log)
{
int result;
diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c
index 888cc4a6252..1808dfc800a 100644
--- a/plugin/server_audit/server_audit.c
+++ b/plugin/server_audit/server_audit.c
@@ -16,7 +16,7 @@
#define PLUGIN_VERSION 0x104
-#define PLUGIN_STR_VERSION "1.4.10"
+#define PLUGIN_STR_VERSION "1.4.11"
#define _my_thread_var loc_thread_var
@@ -140,6 +140,7 @@ static int loc_file_errno;
#define logger_write loc_logger_write
#define logger_rotate loc_logger_rotate
#define logger_init_mutexts loc_logger_init_mutexts
+#define logger_time_to_rotate loc_logger_time_to_rotate
static size_t loc_write(File Filedes, const uchar *Buffer, size_t Count)
@@ -554,22 +555,22 @@ static struct st_mysql_show_var audit_status[]=
{0,0,0}
};
-#if defined(HAVE_PSI_INTERFACE) && !defined(FLOGGER_NO_PSI)
-/* These belong to the service initialization */
+#ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key key_LOCK_operations;
-static PSI_mutex_key key_LOCK_atomic;
-static PSI_mutex_key key_LOCK_bigbuffer;
static PSI_mutex_info mutex_key_list[]=
{
{ &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations",
- PSI_FLAG_GLOBAL},
+ PSI_FLAG_GLOBAL}
+#ifndef FLOGGER_NO_PSI
+ ,
{ &key_LOCK_atomic, "SERVER_AUDIT_plugin::lock_atomic",
PSI_FLAG_GLOBAL},
{ &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer",
PSI_FLAG_GLOBAL}
+#endif /*FLOGGER_NO_PSI*/
};
-#endif
-static mysql_mutex_t lock_operations;
+#endif /*HAVE_PSI_INTERFACE*/
+static mysql_prlock_t lock_operations;
static mysql_mutex_t lock_atomic;
static mysql_mutex_t lock_bigbuffer;
@@ -819,6 +820,7 @@ enum sa_keywords
SQLCOM_DML,
SQLCOM_GRANT,
SQLCOM_CREATE_USER,
+ SQLCOM_ALTER_USER,
SQLCOM_CHANGE_MASTER,
SQLCOM_CREATE_SERVER,
SQLCOM_SET_OPTION,
@@ -926,6 +928,7 @@ struct sa_keyword passwd_keywords[]=
{
{3, "SET", &password_word, SQLCOM_SET_OPTION},
{5, "ALTER", &server_word, SQLCOM_ALTER_SERVER},
+ {5, "ALTER", &user_word, SQLCOM_ALTER_USER},
{5, "GRANT", 0, SQLCOM_GRANT},
{6, "CREATE", &user_word, SQLCOM_CREATE_USER},
{6, "CREATE", &server_word, SQLCOM_CREATE_SERVER},
@@ -1320,19 +1323,41 @@ static void change_connection(struct connection_info *cn,
event->ip, event->ip_length);
}
+/*
+ Write to the log
+
+ @param take_lock If set, take a read lock (or write lock on rotate).
+ If not set, the caller has a already taken a write lock
+*/
+
static int write_log(const char *message, size_t len, int take_lock)
{
int result= 0;
if (take_lock)
- flogger_mutex_lock(&lock_operations);
+ {
+ /* Start by taking a read lock */
+ mysql_prlock_rdlock(&lock_operations);
+ }
if (output_type == OUTPUT_FILE)
{
- if (logfile &&
- (is_active= (logger_write(logfile, message, len) == (int) len)))
- goto exit;
- ++log_write_failures;
- result= 1;
+ if (logfile)
+ {
+ my_bool allow_rotate= !take_lock; /* Allow rotate if caller write lock */
+ if (take_lock && logger_time_to_rotate(logfile))
+ {
+ /* We have to rotate the log, change above read lock to write lock */
+ mysql_prlock_unlock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
+ allow_rotate= 1;
+ }
+ if (!(is_active= (logger_write_r(logfile, allow_rotate, message, len) ==
+ (int) len)))
+ {
+ ++log_write_failures;
+ result= 1;
+ }
+ }
}
else if (output_type == OUTPUT_SYSLOG)
{
@@ -1340,9 +1365,8 @@ static int write_log(const char *message, size_t len, int take_lock)
syslog_priority_codes[syslog_priority],
"%s %.*s", syslog_info, (int) len, message);
}
-exit:
if (take_lock)
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
return result;
}
@@ -1590,7 +1614,7 @@ static int do_log_user(const char *name, int len,
return 0;
if (take_lock)
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_rdlock(&lock_operations);
if (incl_user_coll.n_users)
{
@@ -1606,7 +1630,7 @@ static int do_log_user(const char *name, int len,
result= 1;
if (take_lock)
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
return result;
}
@@ -1824,6 +1848,7 @@ do_log_query:
{
case SQLCOM_GRANT:
case SQLCOM_CREATE_USER:
+ case SQLCOM_ALTER_USER:
csize+= escape_string_hide_passwords(query, query_len,
uh_buffer, uh_buffer_size,
"IDENTIFIED", 10, "BY", 2, 0);
@@ -2502,11 +2527,11 @@ static int server_audit_init(void *p __attribute__((unused)))
servhost_len= (uint)strlen(servhost);
logger_init_mutexes();
-#if defined(HAVE_PSI_INTERFACE) && !defined(FLOGGER_NO_PSI)
+#ifdef HAVE_PSI_INTERFACE
if (PSI_server)
PSI_server->register_mutex("server_audit", mutex_key_list, 1);
#endif
- flogger_mutex_init(key_LOCK_operations, &lock_operations, MY_MUTEX_INIT_FAST);
+ mysql_prlock_init(key_LOCK_operations, &lock_operations);
flogger_mutex_init(key_LOCK_operations, &lock_atomic, MY_MUTEX_INIT_FAST);
flogger_mutex_init(key_LOCK_operations, &lock_bigbuffer, MY_MUTEX_INIT_FAST);
@@ -2594,7 +2619,7 @@ static int server_audit_deinit(void *p __attribute__((unused)))
closelog();
(void) free(big_buffer);
- flogger_mutex_destroy(&lock_operations);
+ mysql_prlock_destroy(&lock_operations);
flogger_mutex_destroy(&lock_atomic);
flogger_mutex_destroy(&lock_bigbuffer);
@@ -2705,7 +2730,7 @@ static void update_file_path(MYSQL_THD thd,
fprintf(stderr, "Log file name was changed to '%s'.\n", new_name);
if (!maria_55_started || !debug_server_started)
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
if (logging)
log_current_query(thd);
@@ -2737,7 +2762,7 @@ static void update_file_path(MYSQL_THD thd,
file_path= path_buffer;
exit_func:
if (!maria_55_started || !debug_server_started)
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
ADD_ATOMIC(internal_stop_logging, -1);
}
@@ -2753,9 +2778,9 @@ static void update_file_rotations(MYSQL_THD thd __attribute__((unused)),
if (!logging || output_type != OUTPUT_FILE)
return;
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
logfile->rotations= rotations;
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
}
@@ -2771,9 +2796,9 @@ static void update_file_rotate_size(MYSQL_THD thd __attribute__((unused)),
if (!logging || output_type != OUTPUT_FILE)
return;
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
logfile->size_limit= file_rotate_size;
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
}
@@ -2818,7 +2843,7 @@ static void update_incl_users(MYSQL_THD thd,
char *new_users= (*(char **) save) ? *(char **) save : empty_str;
size_t new_len= strlen(new_users) + 1;
if (!maria_55_started || !debug_server_started)
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
mark_always_logged(thd);
if (new_len > sizeof(incl_user_buffer))
@@ -2832,7 +2857,7 @@ static void update_incl_users(MYSQL_THD thd,
error_header();
fprintf(stderr, "server_audit_incl_users set to '%s'.\n", incl_users);
if (!maria_55_started || !debug_server_started)
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
}
@@ -2843,7 +2868,7 @@ static void update_excl_users(MYSQL_THD thd __attribute__((unused)),
char *new_users= (*(char **) save) ? *(char **) save : empty_str;
size_t new_len= strlen(new_users) + 1;
if (!maria_55_started || !debug_server_started)
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
mark_always_logged(thd);
if (new_len > sizeof(excl_user_buffer))
@@ -2857,7 +2882,7 @@ static void update_excl_users(MYSQL_THD thd __attribute__((unused)),
error_header();
fprintf(stderr, "server_audit_excl_users set to '%s'.\n", excl_users);
if (!maria_55_started || !debug_server_started)
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
}
@@ -2870,7 +2895,7 @@ static void update_output_type(MYSQL_THD thd,
return;
ADD_ATOMIC(internal_stop_logging, 1);
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
if (logging)
{
log_current_query(thd);
@@ -2884,7 +2909,7 @@ static void update_output_type(MYSQL_THD thd,
if (logging)
start_logging();
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
ADD_ATOMIC(internal_stop_logging, -1);
}
@@ -2914,9 +2939,9 @@ static void update_syslog_priority(MYSQL_THD thd __attribute__((unused)),
if (syslog_priority == new_priority)
return;
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
mark_always_logged(thd);
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
error_header();
fprintf(stderr, "SysLog priority was changed from '%s' to '%s'.\n",
syslog_priority_names[syslog_priority],
@@ -2935,7 +2960,7 @@ static void update_logging(MYSQL_THD thd,
ADD_ATOMIC(internal_stop_logging, 1);
if (!maria_55_started || !debug_server_started)
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
if ((logging= new_logging))
{
start_logging();
@@ -2952,7 +2977,7 @@ static void update_logging(MYSQL_THD thd,
}
if (!maria_55_started || !debug_server_started)
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
ADD_ATOMIC(internal_stop_logging, -1);
}
@@ -2967,13 +2992,13 @@ static void update_mode(MYSQL_THD thd __attribute__((unused)),
ADD_ATOMIC(internal_stop_logging, 1);
if (!maria_55_started || !debug_server_started)
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
mark_always_logged(thd);
error_header();
fprintf(stderr, "Logging mode was changed from %d to %d.\n", mode, new_mode);
mode= new_mode;
if (!maria_55_started || !debug_server_started)
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
ADD_ATOMIC(internal_stop_logging, -1);
}
@@ -2988,14 +3013,14 @@ static void update_syslog_ident(MYSQL_THD thd __attribute__((unused)),
syslog_ident= syslog_ident_buffer;
error_header();
fprintf(stderr, "SYSYLOG ident was changed to '%s'\n", syslog_ident);
- flogger_mutex_lock(&lock_operations);
+ mysql_prlock_wrlock(&lock_operations);
mark_always_logged(thd);
if (logging && output_type == OUTPUT_SYSLOG)
{
stop_logging();
start_logging();
}
- flogger_mutex_unlock(&lock_operations);
+ mysql_prlock_unlock(&lock_operations);
}
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index cdfde2cc3ee..d52f44f9b95 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -9182,7 +9182,6 @@ int ha_partition::extra(enum ha_extra_function operation)
case HA_EXTRA_STARTING_ORDERED_INDEX_SCAN:
case HA_EXTRA_BEGIN_ALTER_COPY:
case HA_EXTRA_END_ALTER_COPY:
- case HA_EXTRA_FAKE_START_STMT:
DBUG_RETURN(loop_partitions(extra_cb, &operation));
default:
{
diff --git a/sql/handler.h b/sql/handler.h
index b0a90f24494..b00643d0ace 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1799,6 +1799,12 @@ handlerton *ha_default_tmp_handlerton(THD *thd);
*/
#define HTON_TRANSACTIONAL_AND_NON_TRANSACTIONAL (1 << 17)
+/*
+ Table requires and close and reopen after truncate
+ If the handler has HTON_CAN_RECREATE, this flag is not used
+*/
+#define HTON_REQUIRES_CLOSE_AFTER_TRUNCATE (1 << 18)
+
class Ha_trx_info;
struct THD_TRANS
diff --git a/sql/item.cc b/sql/item.cc
index f818a9f02e7..7caa9e41e2f 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9372,7 +9372,7 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
def_field->reset_fields();
// If non-constant default value expression or a blob
if (def_field->default_value &&
- (def_field->default_value->flags || def_field->flags & BLOB_FLAG))
+ (def_field->default_value->flags || (def_field->flags & BLOB_FLAG)))
{
uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length());
if (!newptr)
@@ -9476,11 +9476,60 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
return Item_field::save_in_field(field_arg, no_conversions);
}
+double Item_default_value::val_result()
+{
+ calculate();
+ return Item_field::val_result();
+}
+
+longlong Item_default_value::val_int_result()
+{
+ calculate();
+ return Item_field::val_int_result();
+}
+
+String *Item_default_value::str_result(String* tmp)
+{
+ calculate();
+ return Item_field::str_result(tmp);
+}
+
+bool Item_default_value::val_bool_result()
+{
+ calculate();
+ return Item_field::val_bool_result();
+}
+
+bool Item_default_value::is_null_result()
+{
+ calculate();
+ return Item_field::is_null_result();
+}
+
+my_decimal *Item_default_value::val_decimal_result(my_decimal *decimal_value)
+{
+ calculate();
+ return Item_field::val_decimal_result(decimal_value);
+}
+
+bool Item_default_value::get_date_result(THD *thd, MYSQL_TIME *ltime,
+ date_mode_t fuzzydate)
+{
+ calculate();
+ return Item_field::get_date_result(thd, ltime, fuzzydate);
+}
+
+bool Item_default_value::val_native_result(THD *thd, Native *to)
+{
+ calculate();
+ return Item_field::val_native_result(thd, to);
+}
+
table_map Item_default_value::used_tables() const
{
if (!field || !field->default_value)
return static_cast<table_map>(0);
- if (!field->default_value->expr) // not fully parsed field
+ if (!field->default_value->expr) // not fully parsed field
return static_cast<table_map>(RAND_TABLE_BIT);
return field->default_value->expr->used_tables();
}
diff --git a/sql/item.h b/sql/item.h
index 03c5ad06fa9..2a87081584d 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2,7 +2,7 @@
#define SQL_ITEM_INCLUDED
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
- Copyright (c) 2009, 2020, MariaDB Corporation.
+ Copyright (c) 2009, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -6428,6 +6428,17 @@ public:
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate);
bool val_native(THD *thd, Native *to);
+ bool val_native_result(THD *thd, Native *to);
+
+ /* Result variants */
+ double val_result();
+ longlong val_int_result();
+ String *str_result(String* tmp);
+ my_decimal *val_decimal_result(my_decimal *val);
+ bool val_bool_result();
+ bool is_null_result();
+ bool get_date_result(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate);
+
bool send(Protocol *protocol, st_value *buffer);
int save_in_field(Field *field_arg, bool no_conversions);
bool save_in_param(THD *thd, Item_param *param)
@@ -6456,6 +6467,8 @@ public:
}
Item *transform(THD *thd, Item_transformer transformer, uchar *args);
+ Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param);
};
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index ee7226afd0b..3f5b15715f9 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -1395,7 +1395,9 @@ bool Sql_cmd_analyze_table::execute(THD *thd)
/*
Presumably, ANALYZE and binlog writing doesn't require synchronization
*/
+ thd->get_stmt_da()->set_overwrite_status(true);
res= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
+ thd->get_stmt_da()->set_overwrite_status(false);
}
m_lex->first_select_lex()->table_list.first= first_table;
m_lex->query_tables= first_table;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index cb960a89cb6..e7fe0b39e3a 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3346,6 +3346,146 @@ bool Sql_cmd_call::execute(THD *thd)
/**
+ Check whether the SQL statement being processed is prepended by
+ SET STATEMENT clause and handle variables assignment if it is.
+
+ @param thd thread handle
+ @param lex current lex
+
+ @return false in case of success, true in case of error.
+*/
+
+bool run_set_statement_if_requested(THD *thd, LEX *lex)
+{
+ if (!lex->stmt_var_list.is_empty() && !thd->slave_thread)
+ {
+ Query_arena backup;
+ DBUG_PRINT("info", ("SET STATEMENT %d vars", lex->stmt_var_list.elements));
+
+ lex->old_var_list.empty();
+ List_iterator_fast<set_var_base> it(lex->stmt_var_list);
+ set_var_base *var;
+
+ if (lex->set_arena_for_set_stmt(&backup))
+ return true;
+
+ MEM_ROOT *mem_root= thd->mem_root;
+ while ((var= it++))
+ {
+ DBUG_ASSERT(var->is_system());
+ set_var *o= NULL, *v= (set_var*)var;
+ if (!v->var->is_set_stmt_ok())
+ {
+ my_error(ER_SET_STATEMENT_NOT_SUPPORTED, MYF(0), v->var->name.str);
+ lex->reset_arena_for_set_stmt(&backup);
+ lex->old_var_list.empty();
+ lex->free_arena_for_set_stmt();
+ return true;
+ }
+ if (v->var->session_is_default(thd))
+ o= new set_var(thd,v->type, v->var, &v->base, NULL);
+ else
+ {
+ switch (v->var->option.var_type & GET_TYPE_MASK)
+ {
+ case GET_BOOL:
+ case GET_INT:
+ case GET_LONG:
+ case GET_LL:
+ {
+ bool null_value;
+ longlong val= v->var->val_int(&null_value, thd, v->type, &v->base);
+ o= new set_var(thd, v->type, v->var, &v->base,
+ (null_value ?
+ (Item *) new (mem_root) Item_null(thd) :
+ (Item *) new (mem_root) Item_int(thd, val)));
+ }
+ break;
+ case GET_UINT:
+ case GET_ULONG:
+ case GET_ULL:
+ {
+ bool null_value;
+ ulonglong val= v->var->val_int(&null_value, thd, v->type, &v->base);
+ o= new set_var(thd, v->type, v->var, &v->base,
+ (null_value ?
+ (Item *) new (mem_root) Item_null(thd) :
+ (Item *) new (mem_root) Item_uint(thd, val)));
+ }
+ break;
+ case GET_DOUBLE:
+ {
+ bool null_value;
+ double val= v->var->val_real(&null_value, thd, v->type, &v->base);
+ o= new set_var(thd, v->type, v->var, &v->base,
+ (null_value ?
+ (Item *) new (mem_root) Item_null(thd) :
+ (Item *) new (mem_root) Item_float(thd, val, 1)));
+ }
+ break;
+ default:
+ case GET_NO_ARG:
+ case GET_DISABLED:
+ DBUG_ASSERT(0);
+ /* fall through */
+ case 0:
+ case GET_FLAGSET:
+ case GET_ENUM:
+ case GET_SET:
+ case GET_STR:
+ case GET_STR_ALLOC:
+ {
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), v->var->charset(thd)),*val;
+ val= v->var->val_str(&tmp, thd, v->type, &v->base);
+ if (val)
+ {
+ Item_string *str=
+ new (mem_root) Item_string(thd, v->var->charset(thd),
+ val->ptr(), val->length());
+ o= new set_var(thd, v->type, v->var, &v->base, str);
+ }
+ else
+ o= new set_var(thd, v->type, v->var, &v->base,
+ new (mem_root) Item_null(thd));
+ }
+ break;
+ }
+ }
+ DBUG_ASSERT(o);
+ lex->old_var_list.push_back(o, thd->mem_root);
+ }
+ lex->reset_arena_for_set_stmt(&backup);
+
+ if (lex->old_var_list.is_empty())
+ lex->free_arena_for_set_stmt();
+
+ if (thd->is_error() ||
+ sql_set_variables(thd, &lex->stmt_var_list, false))
+ {
+ if (!thd->is_error())
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "SET");
+ lex->restore_set_statement_var();
+ return true;
+ }
+ /*
+ The value of last_insert_id is remembered in THD to be written to binlog
+ when it's used *the first time* in the statement. But SET STATEMENT
+ must read the old value of last_insert_id to be able to restore it at
+ the end. This should not count at "reading of last_insert_id" and
+ should not remember last_insert_id for binlog. That is, it should clear
+ stmt_depends_on_first_successful_insert_id_in_prev_stmt flag.
+ */
+ if (!thd->in_sub_stmt)
+ {
+ thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
+ }
+ }
+ return false;
+}
+
+
+/**
Execute command saved in thd and lex->sql_command.
@param thd Thread handle
@@ -3631,127 +3771,13 @@ mysql_execute_command(THD *thd)
thd->get_binlog_format(&orig_binlog_format,
&orig_current_stmt_binlog_format);
- if (!lex->stmt_var_list.is_empty() && !thd->slave_thread)
- {
- Query_arena backup;
- DBUG_PRINT("info", ("SET STATEMENT %d vars", lex->stmt_var_list.elements));
-
- lex->old_var_list.empty();
- List_iterator_fast<set_var_base> it(lex->stmt_var_list);
- set_var_base *var;
-
- if (lex->set_arena_for_set_stmt(&backup))
- goto error;
-
- MEM_ROOT *mem_root= thd->mem_root;
- while ((var= it++))
- {
- DBUG_ASSERT(var->is_system());
- set_var *o= NULL, *v= (set_var*)var;
- if (!v->var->is_set_stmt_ok())
- {
- my_error(ER_SET_STATEMENT_NOT_SUPPORTED, MYF(0), v->var->name.str);
- lex->reset_arena_for_set_stmt(&backup);
- lex->old_var_list.empty();
- lex->free_arena_for_set_stmt();
- goto error;
- }
- if (v->var->session_is_default(thd))
- o= new set_var(thd,v->type, v->var, &v->base, NULL);
- else
- {
- switch (v->var->option.var_type & GET_TYPE_MASK)
- {
- case GET_BOOL:
- case GET_INT:
- case GET_LONG:
- case GET_LL:
- {
- bool null_value;
- longlong val= v->var->val_int(&null_value, thd, v->type, &v->base);
- o= new set_var(thd, v->type, v->var, &v->base,
- (null_value ?
- (Item *) new (mem_root) Item_null(thd) :
- (Item *) new (mem_root) Item_int(thd, val)));
- }
- break;
- case GET_UINT:
- case GET_ULONG:
- case GET_ULL:
- {
- bool null_value;
- ulonglong val= v->var->val_int(&null_value, thd, v->type, &v->base);
- o= new set_var(thd, v->type, v->var, &v->base,
- (null_value ?
- (Item *) new (mem_root) Item_null(thd) :
- (Item *) new (mem_root) Item_uint(thd, val)));
- }
- break;
- case GET_DOUBLE:
- {
- bool null_value;
- double val= v->var->val_real(&null_value, thd, v->type, &v->base);
- o= new set_var(thd, v->type, v->var, &v->base,
- (null_value ?
- (Item *) new (mem_root) Item_null(thd) :
- (Item *) new (mem_root) Item_float(thd, val, 1)));
- }
- break;
- default:
- case GET_NO_ARG:
- case GET_DISABLED:
- DBUG_ASSERT(0);
- /* fall through */
- case 0:
- case GET_FLAGSET:
- case GET_ENUM:
- case GET_SET:
- case GET_STR:
- case GET_STR_ALLOC:
- {
- char buff[STRING_BUFFER_USUAL_SIZE];
- String tmp(buff, sizeof(buff), v->var->charset(thd)),*val;
- val= v->var->val_str(&tmp, thd, v->type, &v->base);
- if (val)
- {
- Item_string *str= new (mem_root) Item_string(thd, v->var->charset(thd),
- val->ptr(), val->length());
- o= new set_var(thd, v->type, v->var, &v->base, str);
- }
- else
- o= new set_var(thd, v->type, v->var, &v->base,
- new (mem_root) Item_null(thd));
- }
- break;
- }
- }
- DBUG_ASSERT(o);
- lex->old_var_list.push_back(o, thd->mem_root);
- }
- lex->reset_arena_for_set_stmt(&backup);
- if (lex->old_var_list.is_empty())
- lex->free_arena_for_set_stmt();
- if (thd->is_error() ||
- (res= sql_set_variables(thd, &lex->stmt_var_list, false)))
- {
- if (!thd->is_error())
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "SET");
- lex->restore_set_statement_var();
- goto error;
- }
- /*
- The value of last_insert_id is remembered in THD to be written to binlog
- when it's used *the first time* in the statement. But SET STATEMENT
- must read the old value of last_insert_id to be able to restore it at
- the end. This should not count at "reading of last_insert_id" and
- should not remember last_insert_id for binlog. That is, it should clear
- stmt_depends_on_first_successful_insert_id_in_prev_stmt flag.
- */
- if (!thd->in_sub_stmt)
- {
- thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
- }
- }
+ /*
+ Assign system variables with values specified by the clause
+ SET STATEMENT var1=value1 [, var2=value2, ...] FOR <statement>
+ if they are any.
+ */
+ if (run_set_statement_if_requested(thd, lex))
+ goto error;
if (thd->lex->mi.connection_name.str == NULL)
thd->lex->mi.connection_name= thd->variables.default_master_connection;
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index 0e5cc7f4bad..ac5786dbaa0 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -100,6 +100,7 @@ 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);
int bootstrap(MYSQL_FILE *file);
+bool run_set_statement_if_requested(THD *thd, LEX *lex);
int mysql_execute_command(THD *thd);
bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd,
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 21c8f739dd2..33ced717ab9 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -4260,6 +4260,16 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
*/
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
+ /*
+ Set variables specified by
+ SET STATEMENT var1=value1 [, var2=value2, ...] FOR <statement>
+ clause for duration of prepare phase. Original values of variable
+ listed in the SET STATEMENT clause is restored right after return
+ from the function check_prepared_statement()
+ */
+ if (likely(error == 0))
+ error= run_set_statement_if_requested(thd, lex);
+
/*
The only case where we should have items in the thd->free_list is
after stmt->set_params_from_vars(), which may in some cases create
@@ -4278,6 +4288,12 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_PREPARE;
}
+ /*
+ Restore original values of variables modified on handling
+ SET STATEMENT clause.
+ */
+ thd->lex->restore_set_statement_var();
+
/* The order is important */
lex->unit.cleanup();
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2f88d4f9217..5443d60efe0 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2009, 2020, MariaDB Corporation.
+ Copyright (c) 2009, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -4682,6 +4682,9 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
}
else
{
+ if (thd->lex->describe)
+ select_options|= SELECT_DESCRIBE;
+
/*
When in EXPLAIN, delay deleting the joins so that they are still
available when we're producing EXPLAIN EXTENDED warning text.
@@ -14499,22 +14502,71 @@ return_zero_rows(JOIN *join, select_result *result, List<TABLE_LIST> &tables,
DBUG_RETURN(0);
}
-/*
- used only in JOIN::clear
+/**
+ used only in JOIN::clear (always) and in do_select()
+ (if there where no matching rows)
+
+ @param join JOIN
+ @param cleared_tables If not null, clear also const tables and mark all
+ cleared tables in the map. cleared_tables is only
+ set when called from do_select() when there is a
+ group function and there where no matching rows.
*/
-static void clear_tables(JOIN *join)
+
+static void clear_tables(JOIN *join, table_map *cleared_tables)
{
/*
- must clear only the non-const tables, as const tables
- are not re-calculated.
+ must clear only the non-const tables as const tables are not re-calculated.
*/
for (uint i= 0 ; i < join->table_count ; i++)
{
- if (!(join->table[i]->map & join->const_table_map))
- mark_as_null_row(join->table[i]); // All fields are NULL
+ TABLE *table= join->table[i];
+
+ if (table->null_row)
+ continue; // Nothing more to do
+ if (!(table->map & join->const_table_map) || cleared_tables)
+ {
+ if (cleared_tables)
+ {
+ (*cleared_tables)|= (((table_map) 1) << i);
+ if (table->s->null_bytes)
+ {
+ /*
+ Remember null bits for the record so that we can restore the
+ original const record in unclear_tables()
+ */
+ memcpy(table->record[1], table->null_flags, table->s->null_bytes);
+ }
+ }
+ mark_as_null_row(table); // All fields are NULL
+ }
+ }
+}
+
+
+/**
+ Reverse null marking for tables and restore null bits.
+
+ We have to do this because the tables may be re-used in a sub query
+ and the subquery will assume that the const tables contains the original
+ data before clear_tables().
+*/
+
+static void unclear_tables(JOIN *join, table_map *cleared_tables)
+{
+ for (uint i= 0 ; i < join->table_count ; i++)
+ {
+ if ((*cleared_tables) & (((table_map) 1) << i))
+ {
+ TABLE *table= join->table[i];
+ if (table->s->null_bytes)
+ memcpy(table->null_flags, table->record[1], table->s->null_bytes);
+ unmark_as_null_row(table);
+ }
}
}
+
/*****************************************************************************
Make som simple condition optimization:
If there is a test 'field = const' change all refs to 'field' to 'const'
@@ -17985,17 +18037,34 @@ Field *Item_field::create_tmp_field_ex(MEM_ROOT *root, TABLE *table,
src->set_field(field);
if (!(result= create_tmp_field_from_item_field(root, table, NULL, param)))
return NULL;
- /*
- Fields that are used as arguments to the DEFAULT() function already have
- their data pointers set to the default value during name resolution. See
- Item_default_value::fix_fields.
- */
- if (type() != Item::DEFAULT_VALUE_ITEM && field->eq_def(result))
+ if (field->eq_def(result))
src->set_default_field(field);
return result;
}
+Field *Item_default_value::create_tmp_field_ex(MEM_ROOT *root, TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ if (field->default_value && (field->flags & BLOB_FLAG))
+ {
+ /*
+ We have to use a copy function when using a blob with default value
+ as the we have to calculate the default value before we can use it.
+ */
+ get_tmp_field_src(src, param);
+ return tmp_table_field_from_field_type(root, table);
+ }
+ /*
+ Same code as in Item_field::create_tmp_field_ex, except no default field
+ handling
+ */
+ src->set_field(field);
+ return create_tmp_field_from_item_field(root, table, nullptr, param);
+}
+
+
Field *Item_ref::create_tmp_field_ex(MEM_ROOT *root, TABLE *table,
Tmp_field_src *src,
const Tmp_field_param *param)
@@ -18097,7 +18166,13 @@ Field *Item_func_sp::create_tmp_field_ex(MEM_ROOT *root, TABLE *table,
the record in the original table.
If modify_item is 0 then fill_record() will update
the temporary table
-
+ @param table_cant_handle_bit_fields
+ Set to 1 if the temporary table cannot handle bit
+ fields. Only set for heap tables when the bit field
+ is part of an index.
+ @param make_copy_field
+ Set when using with rollup when we want to have
+ an exact copy of the field.
@retval
0 on error
@retval
@@ -20162,6 +20237,7 @@ do_select(JOIN *join, Procedure *procedure)
if (join->only_const_tables() && !join->need_tmp)
{
Next_select_func end_select= setup_end_select_func(join, NULL);
+
/*
HAVING will be checked after processing aggregate functions,
But WHERE should checked here (we alredy have read tables).
@@ -20188,6 +20264,17 @@ do_select(JOIN *join, Procedure *procedure)
}
else if (join->send_row_on_empty_set())
{
+ table_map cleared_tables= (table_map) 0;
+ if (end_select == end_send_group)
+ {
+ /*
+ Was a grouping query but we did not find any rows. In this case
+ we clear all tables to get null in any referenced fields,
+ like in case of:
+ SELECT MAX(a) AS f1, a AS f2 FROM t1 WHERE VALUE(a) IS NOT NULL
+ */
+ clear_tables(join, &cleared_tables);
+ }
if (!join->having || join->having->val_int())
{
List<Item> *columns_list= (procedure ? &join->procedure_fields_list :
@@ -20195,6 +20282,12 @@ do_select(JOIN *join, Procedure *procedure)
rc= join->result->send_data_with_check(*columns_list,
join->unit, 0) > 0;
}
+ /*
+ We have to remove the null markings from the tables as this table
+ may be part of a sub query that is re-evaluated
+ */
+ if (cleared_tables)
+ unclear_tables(join, &cleared_tables);
}
/*
An error can happen when evaluating the conds
@@ -21175,8 +21268,8 @@ join_read_const_table(THD *thd, JOIN_TAB *tab, POSITION *pos)
if ((table->null_row= MY_TEST((*tab->on_expr_ref)->val_int() == 0)))
mark_as_null_row(table);
}
- if (!table->null_row)
- table->maybe_null=0;
+ if (!table->null_row && ! tab->join->mixed_implicit_grouping)
+ table->maybe_null= 0;
{
JOIN *join= tab->join;
@@ -26334,7 +26427,7 @@ int JOIN::rollup_write_data(uint idx, TMP_TABLE_PARAM *tmp_table_param_arg, TABL
void JOIN::clear()
{
- clear_tables(this);
+ clear_tables(this, 0);
copy_fields(&tmp_table_param);
if (sum_funcs)
diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc
index 2bf99993a50..e699869d644 100644
--- a/sql/sql_truncate.cc
+++ b/sql/sql_truncate.cc
@@ -477,6 +477,15 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
*/
error= handler_truncate(thd, table_ref, FALSE);
+ if (error == TRUNCATE_OK && thd->locked_tables_mode &&
+ (table_ref->table->file->ht->flags &
+ HTON_REQUIRES_CLOSE_AFTER_TRUNCATE))
+ {
+ thd->locked_tables_list.mark_table_for_reopen(thd, table_ref->table);
+ if (unlikely(thd->locked_tables_list.reopen_tables(thd, true)))
+ thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
+ }
+
/*
All effects of a TRUNCATE TABLE operation are committed even if
truncation fails in the case of non transactional tables. Thus, the
diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc
index b9bdd04eede..c48e40ad53a 100644
--- a/sql/sql_tvc.cc
+++ b/sql/sql_tvc.cc
@@ -679,7 +679,7 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl,
st_select_lex *parent_select)
{
LEX *lex= thd->lex;
- select_result *save_result= thd->lex->result;
+ select_result *save_result= lex->result;
uint8 save_derived_tables= lex->derived_tables;
thd->lex->result= NULL;
@@ -760,13 +760,13 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl,
if (arena)
thd->restore_active_arena(arena, &backup);
- thd->lex->result= save_result;
+ lex->result= save_result;
return wrapper_sl;
err:
if (arena)
thd->restore_active_arena(arena, &backup);
- thd->lex->result= save_result;
+ lex->result= save_result;
lex->derived_tables= save_derived_tables;
return 0;
}
@@ -851,14 +851,9 @@ Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl)
{
if (engine->engine_type() == subselect_engine::SINGLE_SELECT_ENGINE)
((subselect_single_select_engine *) engine)->change_select(wrapper_sl);
- lex->current_select= wrapper_sl;
- return wrapper_sl;
- }
- else
- {
- lex->current_select= parent_select;
- return 0;
}
+ lex->current_select= parent_select;
+ return wrapper_sl;
}
diff --git a/sql/table.h b/sql/table.h
index 9eefd915844..58789dc3826 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -3202,6 +3202,12 @@ inline void mark_as_null_row(TABLE *table)
bfill(table->null_flags,table->s->null_bytes,255);
}
+inline void unmark_as_null_row(TABLE *table)
+{
+ table->null_row=0;
+ table->status= STATUS_NO_RECORD;
+}
+
bool is_simple_order(ORDER *order);
class Open_tables_backup;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index f870cf7793b..f18461daaab 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -3834,8 +3834,10 @@ static int innodb_init(void* p)
innobase_hton->show_status = innobase_show_status;
innobase_hton->notify_tabledef_changed= innodb_notify_tabledef_changed;
innobase_hton->flags =
- HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS
- | HTON_NATIVE_SYS_VERSIONING | HTON_WSREP_REPLICATION;
+ HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS |
+ HTON_NATIVE_SYS_VERSIONING |
+ HTON_WSREP_REPLICATION |
+ HTON_REQUIRES_CLOSE_AFTER_TRUNCATE;
#ifdef WITH_WSREP
innobase_hton->abort_transaction=wsrep_abort_transaction;
@@ -15375,10 +15377,6 @@ ha_innobase::extra(
case HA_EXTRA_END_ALTER_COPY:
m_prebuilt->table->skip_alter_undo = 0;
break;
- case HA_EXTRA_FAKE_START_STMT:
- trx_register_for_2pc(m_prebuilt->trx);
- m_prebuilt->sql_stat_start = true;
- break;
default:/* Do nothing */
;
}
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 56f6d971271..d621b6d27b6 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -4158,6 +4158,18 @@ lock_check_dict_lock(
and release possible other transactions waiting because of these locks. */
void lock_release(trx_t* trx)
{
+#ifdef UNIV_DEBUG
+ std::set<table_id_t> to_evict;
+ if (innodb_evict_tables_on_commit_debug && !trx->is_recovered)
+# if 1 /* if dict_stats_exec_sql() were not playing dirty tricks */
+ if (!mutex_own(&dict_sys.mutex))
+# else /* this would be more proper way to do it */
+ if (!trx->dict_operation_lock_mode && !trx->dict_operation)
+# endif
+ for (const auto& p : trx->mod_tables)
+ if (!p.first->is_temporary())
+ to_evict.emplace(p.first->id);
+#endif
ulint count = 0;
trx_id_t max_trx_id = trx_sys.get_max_trx_id();
@@ -4206,6 +4218,25 @@ void lock_release(trx_t* trx)
}
lock_mutex_exit();
+
+#ifdef UNIV_DEBUG
+ if (to_evict.empty()) {
+ return;
+ }
+ mutex_enter(&dict_sys.mutex);
+ lock_mutex_enter();
+ for (table_id_t id : to_evict) {
+ if (dict_table_t *table = dict_table_open_on_id(
+ id, TRUE, DICT_TABLE_OP_OPEN_ONLY_IF_CACHED)) {
+ if (!table->get_ref_count()
+ && !UT_LIST_GET_LEN(table->locks)) {
+ dict_sys.remove(table, true);
+ }
+ }
+ }
+ lock_mutex_exit();
+ mutex_exit(&dict_sys.mutex);
+#endif
}
/* True if a lock mode is S or X */
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 871f8a899fd..a48ab780960 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -1245,16 +1245,6 @@ trx_update_mod_tables_timestamp(
const time_t now = time(NULL);
trx_mod_tables_t::const_iterator end = trx->mod_tables.end();
-#ifdef UNIV_DEBUG
- const bool preserve_tables = !innodb_evict_tables_on_commit_debug
- || trx->is_recovered /* avoid trouble with XA recovery */
-# if 1 /* if dict_stats_exec_sql() were not playing dirty tricks */
- || mutex_own(&dict_sys.mutex)
-# else /* this would be more proper way to do it */
- || trx->dict_operation_lock_mode || trx->dict_operation
-# endif
- ;
-#endif
for (trx_mod_tables_t::const_iterator it = trx->mod_tables.begin();
it != end;
@@ -1270,26 +1260,6 @@ trx_update_mod_tables_timestamp(
intrusive. */
dict_table_t* table = it->first;
table->update_time = now;
-#ifdef UNIV_DEBUG
- if (preserve_tables || table->get_ref_count()
- || UT_LIST_GET_LEN(table->locks)) {
- /* do not evict when committing DDL operations
- or if some other transaction is holding the
- table handle */
- continue;
- }
- /* recheck while holding the mutex that blocks
- table->acquire() */
- mutex_enter(&dict_sys.mutex);
- mutex_enter(&lock_sys.mutex);
- const bool do_evict = !table->get_ref_count()
- && !UT_LIST_GET_LEN(table->locks);
- mutex_exit(&lock_sys.mutex);
- if (do_evict) {
- dict_sys.remove(table, true);
- }
- mutex_exit(&dict_sys.mutex);
-#endif
}
trx->mod_tables.clear();
@@ -1375,16 +1345,9 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
so that there will be no race condition in lock_release(). */
while (UNIV_UNLIKELY(is_referenced()))
ut_delay(srv_spin_wait_delay);
- release_locks();
- id= 0;
}
else
- {
ut_ad(read_only || !rsegs.m_redo.rseg);
- release_locks();
- }
-
- DEBUG_SYNC_C("after_trx_committed_in_memory");
if (read_only || !rsegs.m_redo.rseg)
{
@@ -1397,6 +1360,10 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
is_recovered= false;
}
+ release_locks();
+ id= 0;
+ DEBUG_SYNC_C("after_trx_committed_in_memory");
+
while (dict_table_t *table= UT_LIST_GET_FIRST(lock.evicted_tables))
{
UT_LIST_REMOVE(lock.evicted_tables, table);
diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c
index aa5c598c9c9..ef8bf3b169b 100644
--- a/storage/maria/ma_recovery.c
+++ b/storage/maria/ma_recovery.c
@@ -1464,6 +1464,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id)
}
if (maria_is_crashed(info))
{
+ tprint(tracef, "\n");
eprint(tracef, "Table '%s' is crashed, skipping it. Please repair it with"
" aria_chk -r", share->open_file_name.str);
recovery_found_crashed_tables++;
diff --git a/storage/maria/ma_recovery_util.c b/storage/maria/ma_recovery_util.c
index 3bbda614991..fe43d812600 100644
--- a/storage/maria/ma_recovery_util.c
+++ b/storage/maria/ma_recovery_util.c
@@ -98,6 +98,7 @@ void eprint(FILE *trace_file __attribute__ ((unused)),
fputc('\n', trace_file);
if (trace_file != stderr)
{
+ va_start(args, format);
my_printv_error(HA_ERR_INITIALIZATION, format, MYF(0), args);
}
va_end(args);
diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp
index 0e264a7bbc7..d0608433745 100644
--- a/storage/mroonga/ha_mroonga.cpp
+++ b/storage/mroonga/ha_mroonga.cpp
@@ -550,9 +550,6 @@ static const char *mrn_inspect_extra_function(enum ha_extra_function operation)
case HA_EXTRA_END_ALTER_COPY:
inspected = "HA_EXTRA_END_ALTER_COPY";
break;
- case HA_EXTRA_FAKE_START_STMT:
- inspected = "HA_EXTRA_FAKE_START_STMT";
- break;
#ifdef MRN_HAVE_HA_EXTRA_EXPORT
case HA_EXTRA_EXPORT:
inspected = "HA_EXTRA_EXPORT";