mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
Merge 10.4 into 10.5
This commit is contained in:
commit
10d544aa7b
40 changed files with 771 additions and 275 deletions
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -2061,6 +2061,29 @@ INSERT INTO t1 VALUES ('2032-10-08');
|
|||
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 #
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 #
|
||||
|
|
|
@ -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
|
||||
#
|
||||
#
|
||||
|
|
|
@ -4941,6 +4941,20 @@ EXECUTE stmt;
|
|||
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 #
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
#
|
||||
|
|
|
@ -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 #
|
||||
|
|
|
@ -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'));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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:
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
53
sql/item.cc
53
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();
|
||||
}
|
||||
|
|
15
sql/item.h
15
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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
268
sql/sql_parse.cc
268
sql/sql_parse.cc
|
@ -3345,6 +3345,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.
|
||||
|
||||
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Reference in a new issue