mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 02:05:57 +01:00
Merge 10.3 into 10.4
This commit is contained in:
commit
8bab5bb332
34 changed files with 743 additions and 264 deletions
|
@ -74,7 +74,8 @@ my %debuggers = (
|
||||||
options => '-f -o {log} {exe} {args}',
|
options => '-f -o {log} {exe} {args}',
|
||||||
},
|
},
|
||||||
rr => {
|
rr => {
|
||||||
options => 'record -o {log} {exe} {args}',
|
options => '_RR_TRACE_DIR={log} rr record {exe} {args}',
|
||||||
|
run => 'env',
|
||||||
pre => sub {
|
pre => sub {
|
||||||
::mtr_error('rr requires kernel.perf_event_paranoid <= 1')
|
::mtr_error('rr requires kernel.perf_event_paranoid <= 1')
|
||||||
if ::mtr_grab_file('/proc/sys/kernel/perf_event_paranoid') > 1;
|
if ::mtr_grab_file('/proc/sys/kernel/perf_event_paranoid') > 1;
|
||||||
|
|
|
@ -2941,5 +2941,34 @@ f COUNT(*)
|
||||||
NULL 1
|
NULL 1
|
||||||
DROP TABLE t1;
|
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
|
# End of 10.3 tests
|
||||||
#
|
#
|
||||||
|
|
|
@ -2042,6 +2042,29 @@ INSERT INTO t1 VALUES ('2032-10-08');
|
||||||
SELECT d != '2023-03-04' AS f, COUNT(*) FROM t1 GROUP BY d WITH ROLLUP;
|
SELECT d != '2023-03-04' AS f, COUNT(*) FROM t1 GROUP BY d WITH ROLLUP;
|
||||||
DROP TABLE t1;
|
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 #
|
||||||
--echo # End of 10.3 tests
|
--echo # End of 10.3 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
|
@ -847,6 +847,39 @@ t r
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
DROP FUNCTION next_seq_value;
|
DROP FUNCTION next_seq_value;
|
||||||
DROP TABLE series;
|
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
|
# End of 10.3 tests
|
||||||
#
|
#
|
||||||
# MDEV-18681: AND formula in HAVING with several occurances
|
# MDEV-18681: AND formula in HAVING with several occurances
|
||||||
|
|
|
@ -891,6 +891,27 @@ DROP TABLE t1;
|
||||||
DROP FUNCTION next_seq_value;
|
DROP FUNCTION next_seq_value;
|
||||||
DROP TABLE series;
|
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 # End of 10.3 tests
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
|
|
|
@ -5501,6 +5501,23 @@ EXISTS(SELECT 1 FROM t1 GROUP BY a IN (select a from t1))
|
||||||
0
|
0
|
||||||
DROP TABLE t1;
|
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
|
# End of 10.2 tests
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
|
@ -4941,6 +4941,20 @@ EXECUTE stmt;
|
||||||
EXECUTE stmt;
|
EXECUTE stmt;
|
||||||
DROP TABLE t1;
|
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 #
|
||||||
--echo # End of 10.2 tests
|
--echo # End of 10.2 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
|
@ -1217,6 +1217,31 @@ set @rnd=1;
|
||||||
select @rnd;
|
select @rnd;
|
||||||
@rnd
|
@rnd
|
||||||
0
|
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);
|
create table t (a int);
|
||||||
SET sql_mode=ORACLE;
|
SET sql_mode=ORACLE;
|
||||||
SET STATEMENT myisam_sort_buffer_size=800000 FOR OPTIMIZE TABLE t;
|
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 STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown';
|
||||||
SET sql_mode=default;
|
SET sql_mode=default;
|
||||||
SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown';
|
SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown';
|
||||||
|
# End of 10.4 tests
|
||||||
|
|
|
@ -1137,6 +1137,30 @@ while ($1)
|
||||||
--echo # @rnd should be 0
|
--echo # @rnd should be 0
|
||||||
select @rnd;
|
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);
|
create table t (a int);
|
||||||
SET sql_mode=ORACLE;
|
SET sql_mode=ORACLE;
|
||||||
SET STATEMENT myisam_sort_buffer_size=800000 FOR OPTIMIZE TABLE t;
|
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 STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown';
|
||||||
SET sql_mode=default;
|
SET sql_mode=default;
|
||||||
SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown';
|
SET STATEMENT max_statement_time=30 FOR DELETE FROM mysql.user where user = 'unknown';
|
||||||
|
|
||||||
|
--echo # End of 10.4 tests
|
||||||
|
|
|
@ -2882,8 +2882,12 @@ deallocate prepare stmt;
|
||||||
drop view v1;
|
drop view v1;
|
||||||
drop table t1,t2,t3;
|
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))
|
# MDEV-22610 Crash in INSERT INTO t1 (VALUES (DEFAULT) UNION VALUES (DEFAULT))
|
||||||
#
|
#
|
||||||
|
|
|
@ -1517,9 +1517,13 @@ drop view v1;
|
||||||
drop table t1,t2,t3;
|
drop table t1,t2,t3;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.3 tests
|
--echo # MDEV-24919: subselect formed by TVC and used in set function
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
|
select sum((values(1)));
|
||||||
|
|
||||||
|
--echo End of 10.3 tests
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # MDEV-22610 Crash in INSERT INTO t1 (VALUES (DEFAULT) UNION VALUES (DEFAULT))
|
--echo # MDEV-22610 Crash in INSERT INTO t1 (VALUES (DEFAULT) UNION VALUES (DEFAULT))
|
||||||
--echo #
|
--echo #
|
||||||
|
|
|
@ -4966,7 +4966,7 @@ sub mysqld_start ($$) {
|
||||||
$ENV{'MYSQLD_LAST_CMD'}= "$exe @$args";
|
$ENV{'MYSQLD_LAST_CMD'}= "$exe @$args";
|
||||||
|
|
||||||
My::Debugger::setup_args(\$args, \$exe, $mysqld->name());
|
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
|
# Remove the old pidfile if any
|
||||||
unlink($mysqld->value('pid-file'));
|
unlink($mysqld->value('pid-file'));
|
||||||
|
|
|
@ -57,3 +57,14 @@ disconnect dml;
|
||||||
connection default;
|
connection default;
|
||||||
SET DEBUG_SYNC = RESET;
|
SET DEBUG_SYNC = RESET;
|
||||||
DROP TABLE child, parent;
|
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;
|
||||||
|
|
|
@ -67,3 +67,16 @@ connection default;
|
||||||
SET DEBUG_SYNC = RESET;
|
SET DEBUG_SYNC = RESET;
|
||||||
|
|
||||||
DROP TABLE child, parent;
|
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;
|
||||||
|
|
|
@ -118,6 +118,7 @@ CREATE USER u1 IDENTIFIED BY 'pwd-123';
|
||||||
GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321";
|
GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321";
|
||||||
SET PASSWORD FOR u1 = PASSWORD('pwd 098');
|
SET PASSWORD FOR u1 = PASSWORD('pwd 098');
|
||||||
CREATE USER u3 IDENTIFIED BY '';
|
CREATE USER u3 IDENTIFIED BY '';
|
||||||
|
ALTER USER u3 IDENTIFIED BY 'pwd-456';
|
||||||
drop user u1, u2, u3;
|
drop user u1, u2, u3;
|
||||||
set global server_audit_events='query_ddl';
|
set global server_audit_events='query_ddl';
|
||||||
create table t1(id int);
|
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,roles_mapping,
|
||||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,global_priv,
|
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,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,db,
|
||||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
|
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,tables_priv,
|
||||||
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv,
|
TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,columns_priv,
|
||||||
|
|
|
@ -95,6 +95,7 @@ CREATE USER u1 IDENTIFIED BY 'pwd-123';
|
||||||
GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321";
|
GRANT ALL ON sa_db TO u2 IDENTIFIED BY "pwd-321";
|
||||||
SET PASSWORD FOR u1 = PASSWORD('pwd 098');
|
SET PASSWORD FOR u1 = PASSWORD('pwd 098');
|
||||||
CREATE USER u3 IDENTIFIED BY '';
|
CREATE USER u3 IDENTIFIED BY '';
|
||||||
|
ALTER USER u3 IDENTIFIED BY 'pwd-456';
|
||||||
drop user u1, u2, u3;
|
drop user u1, u2, u3;
|
||||||
|
|
||||||
set global server_audit_events='query_ddl';
|
set global server_audit_events='query_ddl';
|
||||||
|
|
|
@ -20,7 +20,6 @@ sub start_test {
|
||||||
($path, $args) = ($cmd, , [ ])
|
($path, $args) = ($cmd, , [ ])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
my $oldpwd=getcwd();
|
my $oldpwd=getcwd();
|
||||||
chdir $::opt_vardir;
|
chdir $::opt_vardir;
|
||||||
my $proc=My::SafeProcess->new
|
my $proc=My::SafeProcess->new
|
||||||
|
@ -49,12 +48,12 @@ sub start_test {
|
||||||
my ($command, %tests, $prefix);
|
my ($command, %tests, $prefix);
|
||||||
for (@ctest_list) {
|
for (@ctest_list) {
|
||||||
chomp;
|
chomp;
|
||||||
if (/^\d+: Test command: +/) {
|
if (/^\d+: Test command: +([^ \t]+)/) {
|
||||||
$command= $';
|
$command= $1;
|
||||||
$prefix= /libmariadb/ ? 'conc_' : '';
|
$prefix= /libmariadb/ ? 'conc_' : '';
|
||||||
} elsif (/^ +Test +#\d+: +/) {
|
} elsif (/^ +Test +#\d+: ([^ \t]+)/) {
|
||||||
if ($command ne "NOT_AVAILABLE") {
|
if ($command ne "NOT_AVAILABLE" && $command ne "/bin/sh") {
|
||||||
$tests{$prefix.$'}=$command;
|
$tests{$prefix.$1}=$command;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,23 +150,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 logger_vprintf(LOGGER_HANDLE *log, const char* fmt, va_list ap)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
my_off_t filesize;
|
|
||||||
char cvtbuf[1024];
|
char cvtbuf[1024];
|
||||||
size_t n_bytes;
|
size_t n_bytes;
|
||||||
|
|
||||||
flogger_mutex_lock(&log->lock);
|
flogger_mutex_lock(&log->lock);
|
||||||
if (log->rotations > 0)
|
if (logger_time_to_rotate(log) && do_rotate(log))
|
||||||
if ((filesize= my_tell(log->file, MYF(0))) == (my_off_t) -1 ||
|
{
|
||||||
((unsigned long long)filesize >= log->size_limit &&
|
result= -1;
|
||||||
do_rotate(log)))
|
errno= my_errno;
|
||||||
{
|
goto exit; /* Log rotation needed but failed */
|
||||||
result= -1;
|
}
|
||||||
errno= my_errno;
|
|
||||||
goto exit; /* Log rotation needed but failed */
|
|
||||||
}
|
|
||||||
|
|
||||||
n_bytes= my_vsnprintf(cvtbuf, sizeof(cvtbuf), fmt, ap);
|
n_bytes= my_vsnprintf(cvtbuf, sizeof(cvtbuf), fmt, ap);
|
||||||
if (n_bytes >= sizeof(cvtbuf))
|
if (n_bytes >= sizeof(cvtbuf))
|
||||||
|
@ -180,21 +191,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;
|
int result;
|
||||||
my_off_t filesize;
|
|
||||||
|
|
||||||
flogger_mutex_lock(&log->lock);
|
flogger_mutex_lock(&log->lock);
|
||||||
if (log->rotations > 0)
|
if (allow_rotations && logger_time_to_rotate(log) && do_rotate(log))
|
||||||
if ((filesize= my_tell(log->file, MYF(0))) == (my_off_t) -1 ||
|
{
|
||||||
((unsigned long long)filesize >= log->size_limit &&
|
result= -1;
|
||||||
do_rotate(log)))
|
errno= my_errno;
|
||||||
{
|
goto exit; /* Log rotation needed but failed */
|
||||||
result= -1;
|
}
|
||||||
errno= my_errno;
|
|
||||||
goto exit; /* Log rotation needed but failed */
|
|
||||||
}
|
|
||||||
|
|
||||||
result= (int)my_write(log->file, (uchar *) buffer, size, MYF(0));
|
result= (int)my_write(log->file, (uchar *) buffer, size, MYF(0));
|
||||||
|
|
||||||
|
@ -204,6 +212,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 logger_rotate(LOGGER_HANDLE *log)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
|
|
||||||
#define PLUGIN_VERSION 0x104
|
#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
|
#define _my_thread_var loc_thread_var
|
||||||
|
|
||||||
|
@ -140,6 +140,7 @@ static int loc_file_errno;
|
||||||
#define logger_write loc_logger_write
|
#define logger_write loc_logger_write
|
||||||
#define logger_rotate loc_logger_rotate
|
#define logger_rotate loc_logger_rotate
|
||||||
#define logger_init_mutexts loc_logger_init_mutexts
|
#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)
|
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}
|
{0,0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(HAVE_PSI_INTERFACE) && !defined(FLOGGER_NO_PSI)
|
#ifdef HAVE_PSI_INTERFACE
|
||||||
/* These belong to the service initialization */
|
|
||||||
static PSI_mutex_key key_LOCK_operations;
|
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[]=
|
static PSI_mutex_info mutex_key_list[]=
|
||||||
{
|
{
|
||||||
{ &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations",
|
{ &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",
|
{ &key_LOCK_atomic, "SERVER_AUDIT_plugin::lock_atomic",
|
||||||
PSI_FLAG_GLOBAL},
|
PSI_FLAG_GLOBAL},
|
||||||
{ &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer",
|
{ &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer",
|
||||||
PSI_FLAG_GLOBAL}
|
PSI_FLAG_GLOBAL}
|
||||||
|
#endif /*FLOGGER_NO_PSI*/
|
||||||
};
|
};
|
||||||
#endif
|
#endif /*HAVE_PSI_INTERFACE*/
|
||||||
static mysql_mutex_t lock_operations;
|
static mysql_prlock_t lock_operations;
|
||||||
static mysql_mutex_t lock_atomic;
|
static mysql_mutex_t lock_atomic;
|
||||||
static mysql_mutex_t lock_bigbuffer;
|
static mysql_mutex_t lock_bigbuffer;
|
||||||
|
|
||||||
|
@ -819,6 +820,7 @@ enum sa_keywords
|
||||||
SQLCOM_DML,
|
SQLCOM_DML,
|
||||||
SQLCOM_GRANT,
|
SQLCOM_GRANT,
|
||||||
SQLCOM_CREATE_USER,
|
SQLCOM_CREATE_USER,
|
||||||
|
SQLCOM_ALTER_USER,
|
||||||
SQLCOM_CHANGE_MASTER,
|
SQLCOM_CHANGE_MASTER,
|
||||||
SQLCOM_CREATE_SERVER,
|
SQLCOM_CREATE_SERVER,
|
||||||
SQLCOM_SET_OPTION,
|
SQLCOM_SET_OPTION,
|
||||||
|
@ -926,6 +928,7 @@ struct sa_keyword passwd_keywords[]=
|
||||||
{
|
{
|
||||||
{3, "SET", &password_word, SQLCOM_SET_OPTION},
|
{3, "SET", &password_word, SQLCOM_SET_OPTION},
|
||||||
{5, "ALTER", &server_word, SQLCOM_ALTER_SERVER},
|
{5, "ALTER", &server_word, SQLCOM_ALTER_SERVER},
|
||||||
|
{5, "ALTER", &user_word, SQLCOM_ALTER_USER},
|
||||||
{5, "GRANT", 0, SQLCOM_GRANT},
|
{5, "GRANT", 0, SQLCOM_GRANT},
|
||||||
{6, "CREATE", &user_word, SQLCOM_CREATE_USER},
|
{6, "CREATE", &user_word, SQLCOM_CREATE_USER},
|
||||||
{6, "CREATE", &server_word, SQLCOM_CREATE_SERVER},
|
{6, "CREATE", &server_word, SQLCOM_CREATE_SERVER},
|
||||||
|
@ -1320,19 +1323,41 @@ static void change_connection(struct connection_info *cn,
|
||||||
event->ip, event->ip_length);
|
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)
|
static int write_log(const char *message, size_t len, int take_lock)
|
||||||
{
|
{
|
||||||
int result= 0;
|
int result= 0;
|
||||||
if (take_lock)
|
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 (output_type == OUTPUT_FILE)
|
||||||
{
|
{
|
||||||
if (logfile &&
|
if (logfile)
|
||||||
(is_active= (logger_write(logfile, message, len) == (int) len)))
|
{
|
||||||
goto exit;
|
my_bool allow_rotate= !take_lock; /* Allow rotate if caller write lock */
|
||||||
++log_write_failures;
|
if (take_lock && logger_time_to_rotate(logfile))
|
||||||
result= 1;
|
{
|
||||||
|
/* 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)
|
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],
|
syslog_priority_codes[syslog_priority],
|
||||||
"%s %.*s", syslog_info, (int) len, message);
|
"%s %.*s", syslog_info, (int) len, message);
|
||||||
}
|
}
|
||||||
exit:
|
|
||||||
if (take_lock)
|
if (take_lock)
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1590,7 +1614,7 @@ static int do_log_user(const char *name, int len,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (take_lock)
|
if (take_lock)
|
||||||
flogger_mutex_lock(&lock_operations);
|
mysql_prlock_rdlock(&lock_operations);
|
||||||
|
|
||||||
if (incl_user_coll.n_users)
|
if (incl_user_coll.n_users)
|
||||||
{
|
{
|
||||||
|
@ -1606,7 +1630,7 @@ static int do_log_user(const char *name, int len,
|
||||||
result= 1;
|
result= 1;
|
||||||
|
|
||||||
if (take_lock)
|
if (take_lock)
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1824,6 +1848,7 @@ do_log_query:
|
||||||
{
|
{
|
||||||
case SQLCOM_GRANT:
|
case SQLCOM_GRANT:
|
||||||
case SQLCOM_CREATE_USER:
|
case SQLCOM_CREATE_USER:
|
||||||
|
case SQLCOM_ALTER_USER:
|
||||||
csize+= escape_string_hide_passwords(query, query_len,
|
csize+= escape_string_hide_passwords(query, query_len,
|
||||||
uh_buffer, uh_buffer_size,
|
uh_buffer, uh_buffer_size,
|
||||||
"IDENTIFIED", 10, "BY", 2, 0);
|
"IDENTIFIED", 10, "BY", 2, 0);
|
||||||
|
@ -2497,11 +2522,11 @@ static int server_audit_init(void *p __attribute__((unused)))
|
||||||
servhost_len= (uint)strlen(servhost);
|
servhost_len= (uint)strlen(servhost);
|
||||||
|
|
||||||
logger_init_mutexes();
|
logger_init_mutexes();
|
||||||
#if defined(HAVE_PSI_INTERFACE) && !defined(FLOGGER_NO_PSI)
|
#ifdef HAVE_PSI_INTERFACE
|
||||||
if (PSI_server)
|
if (PSI_server)
|
||||||
PSI_server->register_mutex("server_audit", mutex_key_list, 1);
|
PSI_server->register_mutex("server_audit", mutex_key_list, 1);
|
||||||
#endif
|
#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_atomic, MY_MUTEX_INIT_FAST);
|
||||||
flogger_mutex_init(key_LOCK_operations, &lock_bigbuffer, MY_MUTEX_INIT_FAST);
|
flogger_mutex_init(key_LOCK_operations, &lock_bigbuffer, MY_MUTEX_INIT_FAST);
|
||||||
|
|
||||||
|
@ -2589,7 +2614,7 @@ static int server_audit_deinit(void *p __attribute__((unused)))
|
||||||
closelog();
|
closelog();
|
||||||
|
|
||||||
(void) free(big_buffer);
|
(void) free(big_buffer);
|
||||||
flogger_mutex_destroy(&lock_operations);
|
mysql_prlock_destroy(&lock_operations);
|
||||||
flogger_mutex_destroy(&lock_atomic);
|
flogger_mutex_destroy(&lock_atomic);
|
||||||
flogger_mutex_destroy(&lock_bigbuffer);
|
flogger_mutex_destroy(&lock_bigbuffer);
|
||||||
|
|
||||||
|
@ -2700,7 +2725,7 @@ static void update_file_path(MYSQL_THD thd,
|
||||||
fprintf(stderr, "Log file name was changed to '%s'.\n", new_name);
|
fprintf(stderr, "Log file name was changed to '%s'.\n", new_name);
|
||||||
|
|
||||||
if (!maria_55_started || !debug_server_started)
|
if (!maria_55_started || !debug_server_started)
|
||||||
flogger_mutex_lock(&lock_operations);
|
mysql_prlock_wrlock(&lock_operations);
|
||||||
|
|
||||||
if (logging)
|
if (logging)
|
||||||
log_current_query(thd);
|
log_current_query(thd);
|
||||||
|
@ -2732,7 +2757,7 @@ static void update_file_path(MYSQL_THD thd,
|
||||||
file_path= path_buffer;
|
file_path= path_buffer;
|
||||||
exit_func:
|
exit_func:
|
||||||
if (!maria_55_started || !debug_server_started)
|
if (!maria_55_started || !debug_server_started)
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
ADD_ATOMIC(internal_stop_logging, -1);
|
ADD_ATOMIC(internal_stop_logging, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2748,9 +2773,9 @@ static void update_file_rotations(MYSQL_THD thd __attribute__((unused)),
|
||||||
if (!logging || output_type != OUTPUT_FILE)
|
if (!logging || output_type != OUTPUT_FILE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
flogger_mutex_lock(&lock_operations);
|
mysql_prlock_wrlock(&lock_operations);
|
||||||
logfile->rotations= rotations;
|
logfile->rotations= rotations;
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2766,9 +2791,9 @@ static void update_file_rotate_size(MYSQL_THD thd __attribute__((unused)),
|
||||||
if (!logging || output_type != OUTPUT_FILE)
|
if (!logging || output_type != OUTPUT_FILE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
flogger_mutex_lock(&lock_operations);
|
mysql_prlock_wrlock(&lock_operations);
|
||||||
logfile->size_limit= file_rotate_size;
|
logfile->size_limit= file_rotate_size;
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2813,7 +2838,7 @@ static void update_incl_users(MYSQL_THD thd,
|
||||||
char *new_users= (*(char **) save) ? *(char **) save : empty_str;
|
char *new_users= (*(char **) save) ? *(char **) save : empty_str;
|
||||||
size_t new_len= strlen(new_users) + 1;
|
size_t new_len= strlen(new_users) + 1;
|
||||||
if (!maria_55_started || !debug_server_started)
|
if (!maria_55_started || !debug_server_started)
|
||||||
flogger_mutex_lock(&lock_operations);
|
mysql_prlock_wrlock(&lock_operations);
|
||||||
mark_always_logged(thd);
|
mark_always_logged(thd);
|
||||||
|
|
||||||
if (new_len > sizeof(incl_user_buffer))
|
if (new_len > sizeof(incl_user_buffer))
|
||||||
|
@ -2827,7 +2852,7 @@ static void update_incl_users(MYSQL_THD thd,
|
||||||
error_header();
|
error_header();
|
||||||
fprintf(stderr, "server_audit_incl_users set to '%s'.\n", incl_users);
|
fprintf(stderr, "server_audit_incl_users set to '%s'.\n", incl_users);
|
||||||
if (!maria_55_started || !debug_server_started)
|
if (!maria_55_started || !debug_server_started)
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2838,7 +2863,7 @@ static void update_excl_users(MYSQL_THD thd __attribute__((unused)),
|
||||||
char *new_users= (*(char **) save) ? *(char **) save : empty_str;
|
char *new_users= (*(char **) save) ? *(char **) save : empty_str;
|
||||||
size_t new_len= strlen(new_users) + 1;
|
size_t new_len= strlen(new_users) + 1;
|
||||||
if (!maria_55_started || !debug_server_started)
|
if (!maria_55_started || !debug_server_started)
|
||||||
flogger_mutex_lock(&lock_operations);
|
mysql_prlock_wrlock(&lock_operations);
|
||||||
mark_always_logged(thd);
|
mark_always_logged(thd);
|
||||||
|
|
||||||
if (new_len > sizeof(excl_user_buffer))
|
if (new_len > sizeof(excl_user_buffer))
|
||||||
|
@ -2852,7 +2877,7 @@ static void update_excl_users(MYSQL_THD thd __attribute__((unused)),
|
||||||
error_header();
|
error_header();
|
||||||
fprintf(stderr, "server_audit_excl_users set to '%s'.\n", excl_users);
|
fprintf(stderr, "server_audit_excl_users set to '%s'.\n", excl_users);
|
||||||
if (!maria_55_started || !debug_server_started)
|
if (!maria_55_started || !debug_server_started)
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2865,7 +2890,7 @@ static void update_output_type(MYSQL_THD thd,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ADD_ATOMIC(internal_stop_logging, 1);
|
ADD_ATOMIC(internal_stop_logging, 1);
|
||||||
flogger_mutex_lock(&lock_operations);
|
mysql_prlock_wrlock(&lock_operations);
|
||||||
if (logging)
|
if (logging)
|
||||||
{
|
{
|
||||||
log_current_query(thd);
|
log_current_query(thd);
|
||||||
|
@ -2879,7 +2904,7 @@ static void update_output_type(MYSQL_THD thd,
|
||||||
|
|
||||||
if (logging)
|
if (logging)
|
||||||
start_logging();
|
start_logging();
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
ADD_ATOMIC(internal_stop_logging, -1);
|
ADD_ATOMIC(internal_stop_logging, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2909,9 +2934,9 @@ static void update_syslog_priority(MYSQL_THD thd __attribute__((unused)),
|
||||||
if (syslog_priority == new_priority)
|
if (syslog_priority == new_priority)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
flogger_mutex_lock(&lock_operations);
|
mysql_prlock_wrlock(&lock_operations);
|
||||||
mark_always_logged(thd);
|
mark_always_logged(thd);
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
error_header();
|
error_header();
|
||||||
fprintf(stderr, "SysLog priority was changed from '%s' to '%s'.\n",
|
fprintf(stderr, "SysLog priority was changed from '%s' to '%s'.\n",
|
||||||
syslog_priority_names[syslog_priority],
|
syslog_priority_names[syslog_priority],
|
||||||
|
@ -2930,7 +2955,7 @@ static void update_logging(MYSQL_THD thd,
|
||||||
|
|
||||||
ADD_ATOMIC(internal_stop_logging, 1);
|
ADD_ATOMIC(internal_stop_logging, 1);
|
||||||
if (!maria_55_started || !debug_server_started)
|
if (!maria_55_started || !debug_server_started)
|
||||||
flogger_mutex_lock(&lock_operations);
|
mysql_prlock_wrlock(&lock_operations);
|
||||||
if ((logging= new_logging))
|
if ((logging= new_logging))
|
||||||
{
|
{
|
||||||
start_logging();
|
start_logging();
|
||||||
|
@ -2947,7 +2972,7 @@ static void update_logging(MYSQL_THD thd,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!maria_55_started || !debug_server_started)
|
if (!maria_55_started || !debug_server_started)
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
ADD_ATOMIC(internal_stop_logging, -1);
|
ADD_ATOMIC(internal_stop_logging, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2962,13 +2987,13 @@ static void update_mode(MYSQL_THD thd __attribute__((unused)),
|
||||||
|
|
||||||
ADD_ATOMIC(internal_stop_logging, 1);
|
ADD_ATOMIC(internal_stop_logging, 1);
|
||||||
if (!maria_55_started || !debug_server_started)
|
if (!maria_55_started || !debug_server_started)
|
||||||
flogger_mutex_lock(&lock_operations);
|
mysql_prlock_wrlock(&lock_operations);
|
||||||
mark_always_logged(thd);
|
mark_always_logged(thd);
|
||||||
error_header();
|
error_header();
|
||||||
fprintf(stderr, "Logging mode was changed from %d to %d.\n", mode, new_mode);
|
fprintf(stderr, "Logging mode was changed from %d to %d.\n", mode, new_mode);
|
||||||
mode= new_mode;
|
mode= new_mode;
|
||||||
if (!maria_55_started || !debug_server_started)
|
if (!maria_55_started || !debug_server_started)
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
ADD_ATOMIC(internal_stop_logging, -1);
|
ADD_ATOMIC(internal_stop_logging, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2983,14 +3008,14 @@ static void update_syslog_ident(MYSQL_THD thd __attribute__((unused)),
|
||||||
syslog_ident= syslog_ident_buffer;
|
syslog_ident= syslog_ident_buffer;
|
||||||
error_header();
|
error_header();
|
||||||
fprintf(stderr, "SYSYLOG ident was changed to '%s'\n", syslog_ident);
|
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);
|
mark_always_logged(thd);
|
||||||
if (logging && output_type == OUTPUT_SYSLOG)
|
if (logging && output_type == OUTPUT_SYSLOG)
|
||||||
{
|
{
|
||||||
stop_logging();
|
stop_logging();
|
||||||
start_logging();
|
start_logging();
|
||||||
}
|
}
|
||||||
flogger_mutex_unlock(&lock_operations);
|
mysql_prlock_unlock(&lock_operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define HANDLER_INCLUDED
|
#define HANDLER_INCLUDED
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
|
||||||
Copyright (c) 2009, 2020, MariaDB
|
Copyright (c) 2009, 2021, MariaDB
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License
|
modify it under the terms of the GNU General Public License
|
||||||
|
@ -1725,6 +1725,12 @@ handlerton *ha_default_tmp_handlerton(THD *thd);
|
||||||
/* can be replicated by wsrep replication provider plugin */
|
/* can be replicated by wsrep replication provider plugin */
|
||||||
#define HTON_WSREP_REPLICATION (1 << 13)
|
#define HTON_WSREP_REPLICATION (1 << 13)
|
||||||
|
|
||||||
|
/*
|
||||||
|
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;
|
class Ha_trx_info;
|
||||||
|
|
||||||
struct THD_TRANS
|
struct THD_TRANS
|
||||||
|
|
53
sql/item.cc
53
sql/item.cc
|
@ -9297,7 +9297,7 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
|
||||||
def_field->reset_fields();
|
def_field->reset_fields();
|
||||||
// If non-constant default value expression or a blob
|
// If non-constant default value expression or a blob
|
||||||
if (def_field->default_value &&
|
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());
|
uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length());
|
||||||
if (!newptr)
|
if (!newptr)
|
||||||
|
@ -9400,11 +9400,60 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
|
||||||
return Item_field::save_in_field(field_arg, 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
|
table_map Item_default_value::used_tables() const
|
||||||
{
|
{
|
||||||
if (!field || !field->default_value)
|
if (!field || !field->default_value)
|
||||||
return static_cast<table_map>(0);
|
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 static_cast<table_map>(RAND_TABLE_BIT);
|
||||||
return field->default_value->expr->used_tables();
|
return field->default_value->expr->used_tables();
|
||||||
}
|
}
|
||||||
|
|
15
sql/item.h
15
sql/item.h
|
@ -2,7 +2,7 @@
|
||||||
#define SQL_ITEM_INCLUDED
|
#define SQL_ITEM_INCLUDED
|
||||||
|
|
||||||
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
|
/* 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
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -6422,6 +6422,17 @@ public:
|
||||||
my_decimal *val_decimal(my_decimal *decimal_value);
|
my_decimal *val_decimal(my_decimal *decimal_value);
|
||||||
bool get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate);
|
bool get_date(THD *thd, MYSQL_TIME *ltime,date_mode_t fuzzydate);
|
||||||
bool val_native(THD *thd, Native *to);
|
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);
|
bool send(Protocol *protocol, st_value *buffer);
|
||||||
int save_in_field(Field *field_arg, bool no_conversions);
|
int save_in_field(Field *field_arg, bool no_conversions);
|
||||||
bool save_in_param(THD *thd, Item_param *param)
|
bool save_in_param(THD *thd, Item_param *param)
|
||||||
|
@ -6450,6 +6461,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Item *transform(THD *thd, Item_transformer transformer, uchar *args);
|
Item *transform(THD *thd, Item_transformer transformer, uchar *args);
|
||||||
|
Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
|
||||||
|
const Tmp_field_param *param);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
270
sql/sql_parse.cc
270
sql/sql_parse.cc
|
@ -1,5 +1,5 @@
|
||||||
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
|
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
|
||||||
Copyright (c) 2008, 2020, MariaDB
|
Copyright (c) 2008, 2021, MariaDB
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -3305,6 +3305,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.
|
Execute command saved in thd and lex->sql_command.
|
||||||
|
|
||||||
|
@ -3590,127 +3730,13 @@ mysql_execute_command(THD *thd)
|
||||||
thd->get_binlog_format(&orig_binlog_format,
|
thd->get_binlog_format(&orig_binlog_format,
|
||||||
&orig_current_stmt_binlog_format);
|
&orig_current_stmt_binlog_format);
|
||||||
|
|
||||||
if (!lex->stmt_var_list.is_empty() && !thd->slave_thread)
|
/*
|
||||||
{
|
Assign system variables with values specified by the clause
|
||||||
Query_arena backup;
|
SET STATEMENT var1=value1 [, var2=value2, ...] FOR <statement>
|
||||||
DBUG_PRINT("info", ("SET STATEMENT %d vars", lex->stmt_var_list.elements));
|
if they are any.
|
||||||
|
*/
|
||||||
lex->old_var_list.empty();
|
if (run_set_statement_if_requested(thd, lex))
|
||||||
List_iterator_fast<set_var_base> it(lex->stmt_var_list);
|
goto error;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thd->lex->mi.connection_name.str == NULL)
|
if (thd->lex->mi.connection_name.str == NULL)
|
||||||
thd->lex->mi.connection_name= thd->variables.default_master_connection;
|
thd->lex->mi.connection_name= thd->variables.default_master_connection;
|
||||||
|
|
|
@ -100,6 +100,7 @@ void mysql_init_multi_delete(LEX *lex);
|
||||||
bool multi_delete_set_locks_and_link_aux_tables(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 create_table_set_open_action_and_adjust_tables(LEX *lex);
|
||||||
int bootstrap(MYSQL_FILE *file);
|
int bootstrap(MYSQL_FILE *file);
|
||||||
|
bool run_set_statement_if_requested(THD *thd, LEX *lex);
|
||||||
int mysql_execute_command(THD *thd);
|
int mysql_execute_command(THD *thd);
|
||||||
bool do_command(THD *thd);
|
bool do_command(THD *thd);
|
||||||
bool dispatch_command(enum enum_server_command command, THD *thd,
|
bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||||
|
|
|
@ -4241,6 +4241,16 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
||||||
*/
|
*/
|
||||||
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
|
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
|
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
|
after stmt->set_params_from_vars(), which may in some cases create
|
||||||
|
@ -4259,6 +4269,12 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
||||||
lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_PREPARE;
|
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 */
|
/* The order is important */
|
||||||
lex->unit.cleanup();
|
lex->unit.cleanup();
|
||||||
|
|
||||||
|
|
|
@ -4653,6 +4653,9 @@ mysql_select(THD *thd,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (thd->lex->describe)
|
||||||
|
select_options|= SELECT_DESCRIBE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
When in EXPLAIN, delay deleting the joins so that they are still
|
When in EXPLAIN, delay deleting the joins so that they are still
|
||||||
available when we're producing EXPLAIN EXTENDED warning text.
|
available when we're producing EXPLAIN EXTENDED warning text.
|
||||||
|
@ -14392,22 +14395,71 @@ return_zero_rows(JOIN *join, select_result *result, List<TABLE_LIST> &tables,
|
||||||
DBUG_RETURN(0);
|
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
|
must clear only the non-const tables as const tables are not re-calculated.
|
||||||
are not re-calculated.
|
|
||||||
*/
|
*/
|
||||||
for (uint i= 0 ; i < join->table_count ; i++)
|
for (uint i= 0 ; i < join->table_count ; i++)
|
||||||
{
|
{
|
||||||
if (!(join->table[i]->map & join->const_table_map))
|
TABLE *table= join->table[i];
|
||||||
mark_as_null_row(join->table[i]); // All fields are NULL
|
|
||||||
|
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:
|
Make som simple condition optimization:
|
||||||
If there is a test 'field = const' change all refs to 'field' to 'const'
|
If there is a test 'field = const' change all refs to 'field' to 'const'
|
||||||
|
@ -17904,17 +17956,34 @@ Field *Item_field::create_tmp_field_ex(TABLE *table,
|
||||||
src->set_field(field);
|
src->set_field(field);
|
||||||
if (!(result= create_tmp_field_from_item_field(table, NULL, param)))
|
if (!(result= create_tmp_field_from_item_field(table, NULL, param)))
|
||||||
return NULL;
|
return NULL;
|
||||||
/*
|
if (field->eq_def(result))
|
||||||
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))
|
|
||||||
src->set_default_field(field);
|
src->set_default_field(field);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Item_default_value::create_tmp_field_ex(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(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(table, NULL, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Field *Item_ref::create_tmp_field_ex(TABLE *table,
|
Field *Item_ref::create_tmp_field_ex(TABLE *table,
|
||||||
Tmp_field_src *src,
|
Tmp_field_src *src,
|
||||||
const Tmp_field_param *param)
|
const Tmp_field_param *param)
|
||||||
|
@ -18022,7 +18091,13 @@ Field *Item_func_sp::create_tmp_field_ex(TABLE *table,
|
||||||
the record in the original table.
|
the record in the original table.
|
||||||
If modify_item is 0 then fill_record() will update
|
If modify_item is 0 then fill_record() will update
|
||||||
the temporary table
|
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
|
@retval
|
||||||
0 on error
|
0 on error
|
||||||
@retval
|
@retval
|
||||||
|
@ -19886,6 +19961,7 @@ do_select(JOIN *join, Procedure *procedure)
|
||||||
if (join->only_const_tables() && !join->need_tmp)
|
if (join->only_const_tables() && !join->need_tmp)
|
||||||
{
|
{
|
||||||
Next_select_func end_select= setup_end_select_func(join, NULL);
|
Next_select_func end_select= setup_end_select_func(join, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
HAVING will be checked after processing aggregate functions,
|
HAVING will be checked after processing aggregate functions,
|
||||||
But WHERE should checked here (we alredy have read tables).
|
But WHERE should checked here (we alredy have read tables).
|
||||||
|
@ -19912,12 +19988,29 @@ do_select(JOIN *join, Procedure *procedure)
|
||||||
}
|
}
|
||||||
else if (join->send_row_on_empty_set())
|
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())
|
if (!join->having || join->having->val_int())
|
||||||
{
|
{
|
||||||
List<Item> *columns_list= (procedure ? &join->procedure_fields_list :
|
List<Item> *columns_list= (procedure ? &join->procedure_fields_list :
|
||||||
join->fields);
|
join->fields);
|
||||||
rc= join->result->send_data(*columns_list) > 0;
|
rc= join->result->send_data(*columns_list) > 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
|
An error can happen when evaluating the conds
|
||||||
|
@ -20891,8 +20984,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)))
|
if ((table->null_row= MY_TEST((*tab->on_expr_ref)->val_int() == 0)))
|
||||||
mark_as_null_row(table);
|
mark_as_null_row(table);
|
||||||
}
|
}
|
||||||
if (!table->null_row)
|
if (!table->null_row && ! tab->join->mixed_implicit_grouping)
|
||||||
table->maybe_null=0;
|
table->maybe_null= 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
JOIN *join= tab->join;
|
JOIN *join= tab->join;
|
||||||
|
@ -26052,7 +26145,7 @@ int JOIN::rollup_write_data(uint idx, TMP_TABLE_PARAM *tmp_table_param_arg, TABL
|
||||||
|
|
||||||
void JOIN::clear()
|
void JOIN::clear()
|
||||||
{
|
{
|
||||||
clear_tables(this);
|
clear_tables(this, 0);
|
||||||
copy_fields(&tmp_table_param);
|
copy_fields(&tmp_table_param);
|
||||||
|
|
||||||
if (sum_funcs)
|
if (sum_funcs)
|
||||||
|
|
|
@ -465,6 +465,15 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref)
|
||||||
*/
|
*/
|
||||||
error= handler_truncate(thd, table_ref, FALSE);
|
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
|
All effects of a TRUNCATE TABLE operation are committed even if
|
||||||
truncation fails in the case of non transactional tables. Thus, the
|
truncation fails in the case of non transactional tables. Thus, the
|
||||||
|
|
|
@ -647,7 +647,7 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl,
|
||||||
st_select_lex *parent_select)
|
st_select_lex *parent_select)
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
select_result *save_result= thd->lex->result;
|
select_result *save_result= lex->result;
|
||||||
uint8 save_derived_tables= lex->derived_tables;
|
uint8 save_derived_tables= lex->derived_tables;
|
||||||
thd->lex->result= NULL;
|
thd->lex->result= NULL;
|
||||||
|
|
||||||
|
@ -728,13 +728,13 @@ st_select_lex *wrap_tvc(THD *thd, st_select_lex *tvc_sl,
|
||||||
|
|
||||||
if (arena)
|
if (arena)
|
||||||
thd->restore_active_arena(arena, &backup);
|
thd->restore_active_arena(arena, &backup);
|
||||||
thd->lex->result= save_result;
|
lex->result= save_result;
|
||||||
return wrapper_sl;
|
return wrapper_sl;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (arena)
|
if (arena)
|
||||||
thd->restore_active_arena(arena, &backup);
|
thd->restore_active_arena(arena, &backup);
|
||||||
thd->lex->result= save_result;
|
lex->result= save_result;
|
||||||
lex->derived_tables= save_derived_tables;
|
lex->derived_tables= save_derived_tables;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -818,14 +818,9 @@ Item_subselect::wrap_tvc_into_select(THD *thd, st_select_lex *tvc_sl)
|
||||||
{
|
{
|
||||||
if (engine->engine_type() == subselect_engine::SINGLE_SELECT_ENGINE)
|
if (engine->engine_type() == subselect_engine::SINGLE_SELECT_ENGINE)
|
||||||
((subselect_single_select_engine *) engine)->change_select(wrapper_sl);
|
((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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3245,6 +3245,12 @@ inline void mark_as_null_row(TABLE *table)
|
||||||
bfill(table->null_flags,table->s->null_bytes,255);
|
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);
|
bool is_simple_order(ORDER *order);
|
||||||
|
|
||||||
class Open_tables_backup;
|
class Open_tables_backup;
|
||||||
|
|
|
@ -4119,8 +4119,10 @@ static int innodb_init(void* p)
|
||||||
innobase_hton->flush_logs = innobase_flush_logs;
|
innobase_hton->flush_logs = innobase_flush_logs;
|
||||||
innobase_hton->show_status = innobase_show_status;
|
innobase_hton->show_status = innobase_show_status;
|
||||||
innobase_hton->flags =
|
innobase_hton->flags =
|
||||||
HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS
|
HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS |
|
||||||
| HTON_NATIVE_SYS_VERSIONING | HTON_WSREP_REPLICATION;
|
HTON_NATIVE_SYS_VERSIONING |
|
||||||
|
HTON_WSREP_REPLICATION |
|
||||||
|
HTON_REQUIRES_CLOSE_AFTER_TRUNCATE;
|
||||||
|
|
||||||
#ifdef WITH_WSREP
|
#ifdef WITH_WSREP
|
||||||
innobase_hton->abort_transaction=wsrep_abort_transaction;
|
innobase_hton->abort_transaction=wsrep_abort_transaction;
|
||||||
|
|
|
@ -4266,6 +4266,18 @@ lock_check_dict_lock(
|
||||||
and release possible other transactions waiting because of these locks. */
|
and release possible other transactions waiting because of these locks. */
|
||||||
void lock_release(trx_t* trx)
|
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;
|
ulint count = 0;
|
||||||
trx_id_t max_trx_id = trx_sys.get_max_trx_id();
|
trx_id_t max_trx_id = trx_sys.get_max_trx_id();
|
||||||
|
|
||||||
|
@ -4314,6 +4326,25 @@ void lock_release(trx_t* trx)
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_mutex_exit();
|
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 */
|
/* True if a lock mode is S or X */
|
||||||
|
|
|
@ -1272,16 +1272,6 @@ trx_update_mod_tables_timestamp(
|
||||||
const time_t now = time(NULL);
|
const time_t now = time(NULL);
|
||||||
|
|
||||||
trx_mod_tables_t::const_iterator end = trx->mod_tables.end();
|
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();
|
for (trx_mod_tables_t::const_iterator it = trx->mod_tables.begin();
|
||||||
it != end;
|
it != end;
|
||||||
|
@ -1297,26 +1287,6 @@ trx_update_mod_tables_timestamp(
|
||||||
intrusive. */
|
intrusive. */
|
||||||
dict_table_t* table = it->first;
|
dict_table_t* table = it->first;
|
||||||
table->update_time = now;
|
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();
|
trx->mod_tables.clear();
|
||||||
|
@ -1402,16 +1372,9 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
|
||||||
so that there will be no race condition in lock_release(). */
|
so that there will be no race condition in lock_release(). */
|
||||||
while (UNIV_UNLIKELY(is_referenced()))
|
while (UNIV_UNLIKELY(is_referenced()))
|
||||||
ut_delay(srv_spin_wait_delay);
|
ut_delay(srv_spin_wait_delay);
|
||||||
release_locks();
|
|
||||||
id= 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
ut_ad(read_only || !rsegs.m_redo.rseg);
|
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)
|
if (read_only || !rsegs.m_redo.rseg)
|
||||||
{
|
{
|
||||||
|
@ -1424,6 +1387,10 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
|
||||||
is_recovered= false;
|
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))
|
while (dict_table_t *table= UT_LIST_GET_FIRST(lock.evicted_tables))
|
||||||
{
|
{
|
||||||
UT_LIST_REMOVE(lock.evicted_tables, table);
|
UT_LIST_REMOVE(lock.evicted_tables, table);
|
||||||
|
|
|
@ -1453,6 +1453,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id)
|
||||||
}
|
}
|
||||||
if (maria_is_crashed(info))
|
if (maria_is_crashed(info))
|
||||||
{
|
{
|
||||||
|
tprint(tracef, "\n");
|
||||||
eprint(tracef, "Table '%s' is crashed, skipping it. Please repair it with"
|
eprint(tracef, "Table '%s' is crashed, skipping it. Please repair it with"
|
||||||
" aria_chk -r", share->open_file_name.str);
|
" aria_chk -r", share->open_file_name.str);
|
||||||
recovery_found_crashed_tables++;
|
recovery_found_crashed_tables++;
|
||||||
|
|
|
@ -98,6 +98,7 @@ void eprint(FILE *trace_file __attribute__ ((unused)),
|
||||||
fputc('\n', trace_file);
|
fputc('\n', trace_file);
|
||||||
if (trace_file != stderr)
|
if (trace_file != stderr)
|
||||||
{
|
{
|
||||||
|
va_start(args, format);
|
||||||
my_printv_error(HA_ERR_INITIALIZATION, format, MYF(0), args);
|
my_printv_error(HA_ERR_INITIALIZATION, format, MYF(0), args);
|
||||||
}
|
}
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
Loading…
Add table
Reference in a new issue