Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä 2021-03-05 10:36:51 +02:00
commit 8bab5bb332
34 changed files with 743 additions and 264 deletions

View file

@ -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;

View file

@ -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
# #

View file

@ -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 #

View file

@ -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

View file

@ -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 #

View file

@ -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
# #
# #

View file

@ -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 #

View file

@ -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

View file

@ -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

View file

@ -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))
# #

View file

@ -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 #

View file

@ -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'));

View 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;

View file

@ -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;

View file

@ -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,

View file

@ -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';

View file

@ -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;
} }
} }
} }

View file

@ -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;

View file

@ -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);
} }

View file

@ -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

View file

@ -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();
} }

View file

@ -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);
}; };

View file

@ -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;

View file

@ -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,

View file

@ -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();

View file

@ -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)

View file

@ -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

View file

@ -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;
} }

View file

@ -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;

View file

@ -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;

View file

@ -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 */

View file

@ -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);

View file

@ -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++;

View file

@ -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);