1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-24 11:21:21 +03:00

Merge remote-tracking branch 'origin/10.2' into bb-10.2-ext

Conflicts:
	mysql-test/r/cte_recursive.result
	mysql-test/r/derived_cond_pushdown.result
	mysql-test/t/cte_recursive.test
	mysql-test/t/derived_cond_pushdown.test
	sql/datadict.cc
	sql/handler.cc
This commit is contained in:
Monty
2017-11-09 23:21:41 +02:00
100 changed files with 1188 additions and 898 deletions

View File

@@ -1094,7 +1094,7 @@ inline bool is_delimiter_command(char *name, ulong len)
only name(first DELIMITER_NAME_LEN bytes) is checked.
*/
return (len >= DELIMITER_NAME_LEN &&
!my_strnncoll(charset_info, (uchar*) name, DELIMITER_NAME_LEN,
!my_strnncoll(&my_charset_latin1, (uchar*) name, DELIMITER_NAME_LEN,
(uchar *) DELIMITER_NAME, DELIMITER_NAME_LEN));
}

View File

@@ -46,6 +46,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <ut0mem.h>
#include <srv0start.h>
#include <fil0fil.h>
#include <trx0sys.h>
#include <set>
#include <string>
#include <mysqld.h>
@@ -1680,26 +1681,30 @@ copy_back()
ut_crc32_init();
/* copy undo tablespaces */
if (srv_undo_tablespaces > 0) {
dst_dir = (srv_undo_dir && *srv_undo_dir)
? srv_undo_dir : mysql_data_home;
ds_data = ds_create(dst_dir, DS_TYPE_LOCAL);
dst_dir = (srv_undo_dir && *srv_undo_dir)
? srv_undo_dir : mysql_data_home;
for (ulong i = 1; i <= srv_undo_tablespaces; i++) {
char filename[20];
sprintf(filename, "undo%03lu", i);
if (!(ret = copy_or_move_file(filename, filename,
dst_dir, 1))) {
goto cleanup;
}
ds_data = ds_create(dst_dir, DS_TYPE_LOCAL);
for (uint i = 1; i <= TRX_SYS_MAX_UNDO_SPACES; i++) {
char filename[20];
sprintf(filename, "undo%03u", i);
if (!file_exists(filename)) {
break;
}
if (!(ret = copy_or_move_file(filename, filename,
dst_dir, 1))) {
goto cleanup;
}
ds_destroy(ds_data);
ds_data = NULL;
}
ds_destroy(ds_data);
ds_data = NULL;
/* copy redo logs */
dst_dir = (srv_log_group_home_dir && *srv_log_group_home_dir)
? srv_log_group_home_dir : mysql_data_home;
@@ -1825,7 +1830,7 @@ copy_back()
}
}
/* copy buufer pool dump */
/* copy buffer pool dump */
if (innobase_buffer_pool_filename) {
const char *src_name;

View File

@@ -2838,7 +2838,7 @@ static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback)
/* We found a symlink or a file */
if (strlen(fileinfo.name) > 4) {
bool is_isl= false;
if (ends_with(fileinfo.name, ".ibd") || ((is_isl = ends_with(fileinfo.name, ".ibd"))))
if (ends_with(fileinfo.name, ".ibd") || ((is_isl = ends_with(fileinfo.name, ".isl"))))
(*callback)(dbinfo.name, fileinfo.name, is_isl);
}
}

View File

@@ -82,6 +82,8 @@ call mtr.check_testcase();
let $datadir=`select @@datadir`;
list_files $datadir mysql_upgrade_info;
list_files $datadir/test #sql*;
list_files $datadir/mysql #sql*;
--enable_query_log

View File

@@ -1079,3 +1079,71 @@ id select_type table type possible_keys key key_len ref rows Extra
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
NULL UNION RESULT <union1,4> ALL NULL NULL NULL NULL NULL
DROP TABLE t1,t2;
#
# MDEV-13780: tower of embedding CTEs with multiple usage of them
#
create table t1 (a int);
insert into t1 values (3), (2), (4), (7), (1), (2), (5);
with cte_e as
(
with cte_o as
(
with cte_i as (select * from t1 where a < 7)
select * from cte_i where a > 1
)
select * from cte_o as cto_o1 where a < 3
union
select * from cte_o as cto_o2 where a > 4
)
select * from cte_e as cte_e1 where a > 1
union
select * from cte_e as cte_e2;
a
2
5
explain extended with cte_e as
(
with cte_o as
(
with cte_i as (select * from t1 where a < 7)
select * from cte_i where a > 1
)
select * from cte_o as cto_o1 where a < 3
union
select * from cte_o as cto_o2 where a > 4
)
select * from cte_e as cte_e1 where a > 1
union
select * from cte_e as cte_e2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 14 100.00 Using where
2 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
5 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
NULL UNION RESULT <union2,5> ALL NULL NULL NULL NULL NULL NULL
6 UNION <derived9> ALL NULL NULL NULL NULL 14 100.00
9 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
12 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
NULL UNION RESULT <union9,12> ALL NULL NULL NULL NULL NULL NULL
NULL UNION RESULT <union1,6> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1003 with cte_e as (with cte_o as (with cte_i as (/* select#4 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)/* select#3 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)/* select#2 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1 union /* select#5 */ select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1)/* select#1 */ select `cte_e1`.`a` AS `a` from `cte_e` `cte_e1` where `cte_e1`.`a` > 1 union /* select#6 */ select `cte_e2`.`a` AS `a` from `cte_e` `cte_e2`
drop table t1;
#
# MDEV-13753: embedded CTE in a VIEW created in prepared statement
#
SET @sql_query = "
CREATE OR REPLACE VIEW cte_test AS
WITH cte1 AS ( SELECT 1 as a from dual )
, cte2 AS ( SELECT * FROM cte1 )
SELECT * FROM cte2;
";
PREPARE stmt FROM @sql_query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SHOW CREATE VIEW cte_test;
View Create View character_set_client collation_connection
cte_test CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `cte_test` AS with cte1 as (select 1 AS `a`), cte2 as (select `cte1`.`a` AS `a` from `cte1`)select `cte2`.`a` AS `a` from `cte2` latin1 latin1_swedish_ci
SELECT * FROM cte_test;
a
1
DROP VIEW cte_test;

View File

@@ -2882,6 +2882,28 @@ f
set standard_compliant_cte=default;
DROP TABLE t;
#
# mdev-14184: recursive CTE embedded into CTE with multiple references
#
WITH
cte1 AS (
SELECT n FROM (
WITH RECURSIVE rec_cte(n) AS (
SELECT 1 as n1
UNION ALL
SELECT n+1 as n2 FROM rec_cte WHERE n < 3
) SELECT n FROM rec_cte
) AS X
),
cte2 as (
SELECT 2 FROM cte1
)
SELECT *
FROM cte1;
n
1
2
3
#
# MDEV-14217 [db crash] Recursive CTE when SELECT includes new field
#
CREATE TEMPORARY TABLE a_tbl (

View File

@@ -0,0 +1,2 @@
1
1

View File

@@ -8783,6 +8783,47 @@ EXPLAIN
DROP VIEW v2;
DROP TABLE t1,t2;
#
# MDEV-14237: derived with regexp_substr() in select list
#
create table t1 (a char(8));
insert into t1 values ('b'), ('a'), ('xx');
select *
from ( select distinct regexp_substr(t1.a,'^[A-Za-z]+') as f from t1) as t
where t.f = 'a' or t.f = 'b';
f
b
a
explain format=json select *
from ( select distinct regexp_substr(t1.a,'^[A-Za-z]+') as f from t1) as t
where t.f = 'a' or t.f = 'b';
EXPLAIN
{
"query_block": {
"select_id": 1,
"table": {
"table_name": "<derived2>",
"access_type": "ALL",
"rows": 3,
"filtered": 100,
"attached_condition": "t.f = 'a' or t.f = 'b'",
"materialized": {
"query_block": {
"select_id": 2,
"temporary_table": {
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows": 3,
"filtered": 100
}
}
}
}
}
}
}
drop table t1;
#
# MDEV-10855: Pushdown into derived with window functions
#
set @save_optimizer_switch= @@optimizer_switch;

View File

@@ -1458,6 +1458,20 @@ CONCAT(NAME_CONST('name',15),'오')
15오
SET NAMES latin1;
#
# MDEV-14116 INET6_NTOA output is set as null to varchar(39) variable
#
CREATE PROCEDURE p1()
BEGIN
DECLARE ip_full_addr varchar(39) DEFAULT "";
SELECT INET6_NTOA(UNHEX('20000000000000000000000000000000')) into ip_full_addr;
SELECT ip_full_addr;
END;
$$
CALL p1();
ip_full_addr
2000::
DROP PROCEDURE p1;
#
# Start of 10.2 tests
#
#

View File

@@ -934,5 +934,42 @@ f2
foo
set optimizer_switch= @optimizer_switch_save;
DROP TABLE t1;
#
# MDEV-14164: Unknown column error when adding aggregate to function
# in oracle style procedure FOR loop
#
CREATE TABLE t1(id INT, val INT);
CREATE PROCEDURE p1()
BEGIN
DECLARE cur1 CURSOR FOR SELECT * FROM (
SELECT DISTINCT id FROM t1) a
WHERE NOT EXISTS (SELECT * FROM ( SELECT id FROM t1) b
WHERE a.id=b.id);
OPEN cur1;
CLOSE cur1;
OPEN cur1;
CLOSE cur1;
END;
//
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
CREATE TABLE t1(id INT, val INT);
CREATE PROCEDURE p1()
BEGIN
SELECT * FROM (SELECT DISTINCT id FROM t1) a
WHERE NOT a.id IN (SELECT b.id FROM t1 b);
SELECT * FROM (SELECT DISTINCT id FROM t1) a
WHERE NOT EXISTS (SELECT * FROM t1 b WHERE a.id=b.id);
END;
//
CALL p1();
id
id
CALL p1();
id
id
DROP PROCEDURE p1;
DROP TABLE t1;
# End of 10.0 tests
set optimizer_switch=default;

View File

@@ -806,3 +806,27 @@ SUM(a)
NULL
DROP TABLE t1;
End of 5.1 tests
#
# Start of 10.1 tests
#
#
# MDEV-8867 Wrong field type or metadata for COALESCE(bit_column, 1)
#
CREATE TABLE t1 (val bit(1));
INSERT INTO t1 VALUES (0);
CREATE TABLE t2 AS SELECT COALESCE(val, 1) AS c FROM t1;
SELECT * FROM t2;
c
0
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c` decimal(1,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
SELECT COALESCE(val, 1) FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def COALESCE(val, 1) 246 2 1 Y 32896 0 63
COALESCE(val, 1)
0
DROP TABLE t1;

View File

@@ -852,6 +852,17 @@ Warning 1292 Incorrect datetime value: '1'
Warning 1292 Incorrect datetime value: '1'
DROP TABLE t1;
#
# MDEV-14221 Assertion `0' failed in Item::field_type_for_temporal_comparison
#
CREATE TABLE t1 (d DATE);
INSERT INTO t1 VALUES ('1985-05-13'),('1989-12-24');
SELECT d, COUNT(*) FROM t1 GROUP BY d WITH ROLLUP HAVING CASE d WHEN '2017-05-25' THEN 0 ELSE 1 END;
d COUNT(*)
1985-05-13 1
1989-12-24 1
NULL 2
DROP TABLE t1;
#
# End of 10.1 tests
#
#

View File

@@ -1245,6 +1245,20 @@ a b c
2070 00:00:00 00:00:00
DROP TABLE t1,t2;
#
# MDEV-10817 CAST(MAX(DATE'2001-01-01') AS TIME) returns a wrong result
#
SELECT CAST(DATE'2001-01-01' AS TIME);
CAST(DATE'2001-01-01' AS TIME)
00:00:00
SELECT CAST(MAX(DATE'2001-01-01') AS TIME);
CAST(MAX(DATE'2001-01-01') AS TIME)
00:00:00
CREATE FUNCTION f1() RETURNS DATE RETURN DATE'2001-01-01';
SELECT CAST(f1() AS TIME);
CAST(f1() AS TIME)
00:00:00
DROP FUNCTION f1;
#
# End of 10.2 tests
#
#

View File

@@ -0,0 +1,13 @@
CREATE TABLE t(a INT) ENGINE=InnoDB DATA DIRECTORY='table_data_dir';
INSERT INTO t VALUES(1);
# xtrabackup backup
# xtrabackup prepare
DROP TABLE t;
# shutdown server
# remove datadir
# xtrabackup move back
# restart server
SELECT * FROM t;
a
1
DROP TABLE t;

View File

@@ -0,0 +1,23 @@
let $table_data_dir=$MYSQLTEST_VARDIR/ddir;
mkdir $table_data_dir;
--replace_result $table_data_dir table_data_dir
EVAL CREATE TABLE t(a INT) ENGINE=InnoDB DATA DIRECTORY='$table_data_dir';
INSERT INTO t VALUES(1);
echo # xtrabackup backup;
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
--disable_result_log
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
--enable_result_log
--source include/shutdown_mysqld.inc
echo # xtrabackup prepare;
--disable_result_log
exec $XTRABACKUP --prepare --target-dir=$targetdir;
--source include/start_mysqld.inc
DROP TABLE t;
rmdir $table_data_dir;
-- source include/restart_and_restore.inc
--enable_result_log
SELECT * FROM t;
DROP TABLE t;
rmdir $targetdir;
rmdir $table_data_dir;

View File

@@ -1,13 +1,22 @@
call mtr.add_suppression("InnoDB: New log files created");
CREATE TABLE t(i INT) ENGINE INNODB;
CREATE TABLE t(i INT PRIMARY KEY) ENGINE INNODB;
BEGIN;
INSERT INTO t VALUES(2);
connect con1,localhost,root,,;
SET GLOBAL innodb_flush_log_at_trx_commit = 1;
INSERT INTO t VALUES(1);
# Create full backup , modify table, then create incremental/differential backup
INSERT INTO t VALUES(2);
BEGIN;
INSERT INTO t VALUES(0);
DELETE FROM t WHERE i=0;
connection default;
COMMIT;
SELECT * FROM t;
i
1
2
# Prepare full backup, apply incremental one
disconnect con1;
# Restore and check results
# shutdown server
# remove datadir

View File

@@ -5,14 +5,22 @@ call mtr.add_suppression("InnoDB: New log files created");
let $basedir=$MYSQLTEST_VARDIR/tmp/backup;
let $incremental_dir=$MYSQLTEST_VARDIR/tmp/backup_inc1;
CREATE TABLE t(i INT) ENGINE INNODB;
CREATE TABLE t(i INT PRIMARY KEY) ENGINE INNODB;
BEGIN;
INSERT INTO t VALUES(2);
connect (con1,localhost,root,,);
SET GLOBAL innodb_flush_log_at_trx_commit = 1;
INSERT INTO t VALUES(1);
echo # Create full backup , modify table, then create incremental/differential backup;
--disable_result_log
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$basedir;
--enable_result_log
INSERT INTO t VALUES(2);
BEGIN;
INSERT INTO t VALUES(0);
DELETE FROM t WHERE i=0;
connection default;
COMMIT;
SELECT * FROM t;
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --ftwrl-wait-timeout=5 --ftwrl-wait-threshold=300 --ftwrl-wait-query-type=all --target-dir=$incremental_dir --incremental-basedir=$basedir;
@@ -21,6 +29,7 @@ echo # Prepare full backup, apply incremental one;
exec $XTRABACKUP --prepare --target-dir=$basedir;
exec $XTRABACKUP --prepare --target-dir=$basedir --incremental-dir=$incremental_dir ;
disconnect con1;
echo # Restore and check results;
let $targetdir=$basedir;
-- source include/restart_and_restore.inc

View File

@@ -0,0 +1 @@
--partition

View File

@@ -0,0 +1,22 @@
CREATE TABLE t(i int)
ENGINE=InnoDB
PARTITION BY RANGE (i)
(PARTITION p0 VALUES LESS THAN (100),
PARTITION P1 VALUES LESS THAN (200),
PARTITION p2 VALUES LESS THAN (300) DATA DIRECTORY = 'MYSQLTEST_VARDIR/partitdata',
PARTITION p3 VALUES LESS THAN (400) DATA DIRECTORY = 'MYSQLTEST_VARDIR/partitdata',
PARTITION p4 VALUES LESS THAN MAXVALUE);
INSERT INTO t VALUES (1), (101), (201), (301), (401);
DROP TABLE t;
# shutdown server
# remove datadir
# xtrabackup move back
# restart server
SELECT * FROM t;
i
1
101
201
301
401
DROP TABLE t;

View File

@@ -0,0 +1,24 @@
let $targetdir=$MYSQLTEST_VARDIR/backup;
mkdir $targetdir;
mkdir $MYSQLTEST_VARDIR/partitdata;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval CREATE TABLE t(i int)
ENGINE=InnoDB
PARTITION BY RANGE (i)
(PARTITION p0 VALUES LESS THAN (100),
PARTITION P1 VALUES LESS THAN (200),
PARTITION p2 VALUES LESS THAN (300) DATA DIRECTORY = '$MYSQLTEST_VARDIR/partitdata',
PARTITION p3 VALUES LESS THAN (400) DATA DIRECTORY = '$MYSQLTEST_VARDIR/partitdata',
PARTITION p4 VALUES LESS THAN MAXVALUE);
INSERT INTO t VALUES (1), (101), (201), (301), (401);
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir;
exec $XTRABACKUP --prepare --target-dir=$targetdir;
DROP TABLE t;
rmdir $MYSQLTEST_VARDIR/partitdata;
--source include/restart_and_restore.inc
--enable_result_log
SELECT * FROM t;
DROP TABLE t;
rmdir $targetdir;
rmdir $MYSQLTEST_VARDIR/partitdata;

View File

@@ -52,6 +52,7 @@ alter table t1 rename renamed_t1;
set global server_audit_events='connect,query';
select 1,
2,
# comment
3;
1 2 3
1 2 3
@@ -170,7 +171,9 @@ id
2
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');
SET PASSWORD
# comment
FOR u1 = PASSWORD('pwd 098');
SET PASSWORD FOR u1=<secret>;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '<secret>' at line 1
CREATE USER u3 IDENTIFIED BY '';
@@ -262,7 +265,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,index_stats,
TIME,HOSTNAME,root,localhost,ID,ID,RENAME,test,t1|test.renamed_t1,
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'alter table t1 rename renamed_t1',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_events=\'connect,query\'',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select 1, 2, 3',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select 1,\n2,\n# comment\n3',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t2 values (1), (2)',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t2',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t_doesnt_exist',ID
@@ -345,7 +348,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*! select 2*/',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*comment*/ select 2',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT ALL ON sa_db TO u2 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1 = PASSWORD(*****)',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD \n# comment\nFOR u1 = PASSWORD(*****)',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1=<secret>',ID
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0

View File

@@ -52,6 +52,7 @@ alter table t1 rename renamed_t1;
set global server_audit_events='connect,query';
select 1,
2,
# comment
3;
1 2 3
1 2 3
@@ -170,7 +171,9 @@ id
2
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');
SET PASSWORD
# comment
FOR u1 = PASSWORD('pwd 098');
SET PASSWORD FOR u1=<secret>;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '<secret>' at line 1
CREATE USER u3 IDENTIFIED BY '';
@@ -262,7 +265,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,WRITE,mysql,index_stats,
TIME,HOSTNAME,root,localhost,ID,ID,RENAME,test,t1|test.renamed_t1,
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'alter table t1 rename renamed_t1',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_events=\'connect,query\'',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select 1, 2, 3',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select 1,\n2,\n# comment\n3',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'insert into t2 values (1), (2)',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t2',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select * from t_doesnt_exist',ID
@@ -345,7 +348,7 @@ TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*! select 2*/',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'/*comment*/ select 2',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u1 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'GRANT ALL ON sa_db TO u2 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1 = PASSWORD(*****)',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD\n# comment\nFOR u1 = PASSWORD(*****)',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'SET PASSWORD FOR u1=<secret>',ID
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'CREATE USER u3 IDENTIFIED BY *****',0
TIME,HOSTNAME,root,localhost,ID,ID,QUERY,sa_db,'drop user u1, u2, u3',0

View File

@@ -38,6 +38,7 @@ alter table t1 rename renamed_t1;
set global server_audit_events='connect,query';
select 1,
2,
# comment
3;
insert into t2 values (1), (2);
select * from t2;
@@ -106,7 +107,9 @@ insert into t1 values (1), (2);
select * from t1;
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');
SET PASSWORD
# comment
FOR u1 = PASSWORD('pwd 098');
--error 1064
SET PASSWORD FOR u1=<secret>;
CREATE USER u3 IDENTIFIED BY '';

View File

@@ -38,6 +38,7 @@ alter table t1 rename renamed_t1;
set global server_audit_events='connect,query';
select 1,
2,
# comment
3;
insert into t2 values (1), (2);
select * from t2;
@@ -106,7 +107,9 @@ insert into t1 values (1), (2);
select * from t1;
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');
SET PASSWORD
# comment
FOR u1 = PASSWORD('pwd 098');
--error 1064
SET PASSWORD FOR u1=<secret>;
CREATE USER u3 IDENTIFIED BY '';

View File

@@ -1,7 +1,8 @@
SET @orig = @@global.innodb_buffer_pool_dump_now;
SELECT @orig;
@orig
SELECT @@global.innodb_buffer_pool_dump_now;
@@global.innodb_buffer_pool_dump_now
0
SELECT variable_value INTO @old_dump_status FROM information_schema.global_status
WHERE LOWER(variable_name) = 'innodb_buffer_pool_dump_status';
SET GLOBAL innodb_buffer_pool_dump_now = ON;
SELECT @@global.innodb_buffer_pool_dump_now;
@@global.innodb_buffer_pool_dump_now

View File

@@ -1,7 +1,9 @@
SET @orig = @@global.innodb_buffer_pool_dump_pct;
SELECT @@global.innodb_buffer_pool_dump_pct;
@@global.innodb_buffer_pool_dump_pct
SELECT @orig;
@orig
25
SET GLOBAL innodb_buffer_pool_dump_pct=3;
# Do the dump
SET GLOBAL innodb_buffer_pool_dump_pct=20;
SELECT @@global.innodb_buffer_pool_dump_pct;
@@global.innodb_buffer_pool_dump_pct

View File

@@ -1,8 +1,6 @@
SET @orig = @@global.innodb_buffer_pool_load_now;
SELECT @orig;
@orig
SELECT @@global.innodb_buffer_pool_load_now;
@@global.innodb_buffer_pool_load_now
0
SET GLOBAL innodb_buffer_pool_dump_now = ON;
SET GLOBAL innodb_buffer_pool_load_now = ON;
SELECT variable_value
FROM information_schema.global_status

View File

@@ -5,8 +5,31 @@
-- source include/have_innodb.inc
# Check the default value
SET @orig = @@global.innodb_buffer_pool_dump_now;
SELECT @orig;
SELECT @@global.innodb_buffer_pool_dump_now;
-- let $file = `SELECT CONCAT(@@datadir, @@global.innodb_buffer_pool_filename)`
-- error 0,1
-- remove_file $file
SELECT variable_value INTO @old_dump_status FROM information_schema.global_status
WHERE LOWER(variable_name) = 'innodb_buffer_pool_dump_status';
# A previous test could have run buffer pool dump already;
# in this case we want to make sure that the current time is different
# from the timestamp in the status variable.
# We should have had a smart wait condition here, like the commented one below,
# let $wait_condition =
# SELECT TRIM(SUBSTR('$old_status', -8)) != DATE_FORMAT(CURTIME(), '%k:%i:%s');
# -- source include/wait_condition.inc
# ... but we can't because of MDEV-9867, so there will be just sleep instead.
# And it might be not enough to sleep one second, so we'll have to sleep two.
if (`SELECT variable_value LIKE '%completed at%' FROM information_schema.global_status
WHERE LOWER(variable_name) = 'innodb_buffer_pool_dump_status'`)
{
-- sleep 2
}
# Do the dump
SET GLOBAL innodb_buffer_pool_dump_now = ON;
@@ -15,11 +38,11 @@ SELECT @@global.innodb_buffer_pool_dump_now;
# Wait for the dump to complete
let $wait_condition =
SELECT SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) dump completed at '
SELECT variable_value != @old_dump_status
AND SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) dump completed at '
FROM information_schema.global_status
WHERE LOWER(variable_name) = 'innodb_buffer_pool_dump_status';
-- source include/wait_condition.inc
# Confirm that the dump file has been created
-- let $file = `SELECT CONCAT(@@datadir, @@global.innodb_buffer_pool_filename)`
-- file_exists $file

View File

@@ -11,9 +11,17 @@
# Save the default value
SET @orig = @@global.innodb_buffer_pool_dump_pct;
SELECT @orig;
# Check the default value
SELECT @@global.innodb_buffer_pool_dump_pct;
SET GLOBAL innodb_buffer_pool_dump_pct=3;
--echo # Do the dump
--disable_query_log
--disable_result_log
--source innodb_buffer_pool_dump_now_basic.test
--enable_result_log
--enable_query_log
# Set the valid value
SET GLOBAL innodb_buffer_pool_dump_pct=20;

View File

@@ -0,0 +1 @@
--innodb-buffer-pool-load-at-startup=off

View File

@@ -5,44 +5,22 @@
-- source include/have_innodb.inc
# Check the default value
SET @orig = @@global.innodb_buffer_pool_load_now;
SELECT @orig;
SELECT @@global.innodb_buffer_pool_load_now;
let $old_status= `SELECT variable_value FROM information_schema.global_status
WHERE LOWER(variable_name) = 'innodb_buffer_pool_dump_status'`;
# Make sure there is a dump file to load
# A previous test could have run buffer pool dump already;
# in this case we want to make sure that the current time is different
# from the timestamp in the status variable.
# We should have had a smart wait condition here, like the commented one below,
# but we can't because of MDEV-9867, so there will be just sleep instead.
# And it might be not enough to sleep one second, so we'll have to sleep two.
# let $wait_condition =
# SELECT TRIM(SUBSTR('$old_status', -8)) != DATE_FORMAT(CURTIME(), '%k:%i:%s');
# -- source include/wait_condition.inc
if (`SELECT count(*) > 0 FROM information_schema.global_status
WHERE (LOWER(variable_name) = 'innodb_buffer_pool_dump_status' or
LOWER(variable_name) = 'innodb_buffer_pool_load_status')
and variable_value LIKE '%completed at%'`)
{
-- sleep 2
}
# Do the dump
SET GLOBAL innodb_buffer_pool_dump_now = ON;
# Wait for the dump to complete
let $wait_condition =
SELECT variable_value != '$old_status'
AND SUBSTR(variable_value, 1, 33) = 'Buffer pool(s) dump completed at '
FROM information_schema.global_status
WHERE LOWER(variable_name) = 'innodb_buffer_pool_dump_status';
--disable_warnings
-- source include/wait_condition.inc
--enable_warnings
# Confirm the file is really created
-- let $file = `SELECT CONCAT(@@datadir, @@global.innodb_buffer_pool_filename)`
-- error 0,1
-- file_exists $file
if ($errno)
{
# Dump file does not exist, get it created
--disable_query_log
--disable_result_log
--source innodb_buffer_pool_dump_now_basic.test
--enable_result_log
--enable_query_log
}
let $old_load_status=
`SELECT variable_value FROM information_schema.global_status

View File

@@ -743,3 +743,50 @@ eval $q;
eval explain $q;
DROP TABLE t1,t2;
--echo #
--echo # MDEV-13780: tower of embedding CTEs with multiple usage of them
--echo #
create table t1 (a int);
insert into t1 values (3), (2), (4), (7), (1), (2), (5);
let $q=
with cte_e as
(
with cte_o as
(
with cte_i as (select * from t1 where a < 7)
select * from cte_i where a > 1
)
select * from cte_o as cto_o1 where a < 3
union
select * from cte_o as cto_o2 where a > 4
)
select * from cte_e as cte_e1 where a > 1
union
select * from cte_e as cte_e2;
eval $q;
eval explain extended $q;
drop table t1;
--echo #
--echo # MDEV-13753: embedded CTE in a VIEW created in prepared statement
--echo #
SET @sql_query = "
CREATE OR REPLACE VIEW cte_test AS
WITH cte1 AS ( SELECT 1 as a from dual )
, cte2 AS ( SELECT * FROM cte1 )
SELECT * FROM cte2;
";
PREPARE stmt FROM @sql_query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SHOW CREATE VIEW cte_test;
SELECT * FROM cte_test;
DROP VIEW cte_test;

View File

@@ -1928,6 +1928,25 @@ set standard_compliant_cte=default;
DROP TABLE t;
--echo #
--echo # mdev-14184: recursive CTE embedded into CTE with multiple references
--echo #
WITH
cte1 AS (
SELECT n FROM (
WITH RECURSIVE rec_cte(n) AS (
SELECT 1 as n1
UNION ALL
SELECT n+1 as n2 FROM rec_cte WHERE n < 3
) SELECT n FROM rec_cte
) AS X
),
cte2 as (
SELECT 2 FROM cte1
)
SELECT *
FROM cte1;
--echo #
--echo # MDEV-14217 [db crash] Recursive CTE when SELECT includes new field
@@ -1956,3 +1975,4 @@ DROP TABLE a_tbl;
--error ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT
WITH RECURSIVE x AS (SELECT 1,2 UNION ALL SELECT 1 FROM x) SELECT * FROM x;

View File

@@ -0,0 +1,3 @@
DeLiMiTeR A;
SELECT 1 A;
delimiter ;

View File

@@ -0,0 +1,4 @@
source include/not_embedded.inc;
# MDEV-10728
--exec $MYSQL --default-character-set=binary < "t/delimiter_case_mdev_10728.sql"

View File

@@ -1549,6 +1549,23 @@ eval explain format=json $q;
DROP VIEW v2;
DROP TABLE t1,t2;
--echo #
--echo # MDEV-14237: derived with regexp_substr() in select list
--echo #
create table t1 (a char(8));
insert into t1 values ('b'), ('a'), ('xx');
let $q=
select *
from ( select distinct regexp_substr(t1.a,'^[A-Za-z]+') as f from t1) as t
where t.f = 'a' or t.f = 'b';
eval $q;
eval explain format=json $q;
drop table t1;
--echo #
--echo # MDEV-10855: Pushdown into derived with window functions
--echo #
@@ -1834,3 +1851,4 @@ SELECT * FROM v3 JOIN t1 ON (bmax = b);
DROP VIEW v1,v2,v3;
DROP TABLE t1,t2;

View File

@@ -1103,6 +1103,23 @@ SELECT COERCIBILITY(NAME_CONST('name',15));
SELECT CONCAT(NAME_CONST('name',15),'오');
SET NAMES latin1;
--echo #
--echo # MDEV-14116 INET6_NTOA output is set as null to varchar(39) variable
--echo #
DELIMITER $$;
CREATE PROCEDURE p1()
BEGIN
DECLARE ip_full_addr varchar(39) DEFAULT "";
SELECT INET6_NTOA(UNHEX('20000000000000000000000000000000')) into ip_full_addr;
SELECT ip_full_addr;
END;
$$
DELIMITER ;$$
CALL p1();
DROP PROCEDURE p1;
--echo #
--echo # Start of 10.2 tests
--echo #

View File

@@ -423,7 +423,7 @@ create table t1 (
SHOW CREATE TABLE t1;
DROP TABLE t1;
# Test for Bug#93 4.1 protocl crash on corupted frm and SHOW TABLE STATUS
# Test for Bug#93 4.1 protocol crash on corrupted frm and SHOW TABLE STATUS
flush tables;
@@ -437,7 +437,7 @@ show create table t1;
--disable_warnings
drop table if exists t1;
--enable_warnings
--error 1,0
--error 0,1
--remove_file $MYSQLD_DATADIR/test/t1.frm
#

View File

@@ -786,6 +786,46 @@ set optimizer_switch= @optimizer_switch_save;
DROP TABLE t1;
--echo #
--echo # MDEV-14164: Unknown column error when adding aggregate to function
--echo # in oracle style procedure FOR loop
--echo #
CREATE TABLE t1(id INT, val INT);
DELIMITER //;
CREATE PROCEDURE p1()
BEGIN
DECLARE cur1 CURSOR FOR SELECT * FROM (
SELECT DISTINCT id FROM t1) a
WHERE NOT EXISTS (SELECT * FROM ( SELECT id FROM t1) b
WHERE a.id=b.id);
OPEN cur1;
CLOSE cur1;
OPEN cur1;
CLOSE cur1;
END;
//
DELIMITER ;//
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
CREATE TABLE t1(id INT, val INT);
DELIMITER //;
CREATE PROCEDURE p1()
BEGIN
SELECT * FROM (SELECT DISTINCT id FROM t1) a
WHERE NOT a.id IN (SELECT b.id FROM t1 b);
SELECT * FROM (SELECT DISTINCT id FROM t1) a
WHERE NOT EXISTS (SELECT * FROM t1 b WHERE a.id=b.id);
END;
//
DELIMITER ;//
CALL p1();
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
--echo # End of 10.0 tests
#restore defaults

View File

@@ -439,3 +439,22 @@ SELECT SUM(a) FROM t1 GROUP BY c, b, a;
DROP TABLE t1;
--echo End of 5.1 tests
--echo #
--echo # Start of 10.1 tests
--echo #
--echo #
--echo # MDEV-8867 Wrong field type or metadata for COALESCE(bit_column, 1)
--echo #
CREATE TABLE t1 (val bit(1));
INSERT INTO t1 VALUES (0);
CREATE TABLE t2 AS SELECT COALESCE(val, 1) AS c FROM t1;
SELECT * FROM t2;
SHOW CREATE TABLE t2;
DROP TABLE t2;
--enable_metadata
SELECT COALESCE(val, 1) FROM t1;
--disable_metadata
DROP TABLE t1;

View File

@@ -582,6 +582,15 @@ SELECT DATE(a), DATE(b), DATE(c) FROM t1;
SELECT DATE(COALESCE(a)), DATE(COALESCE(b)), DATE(COALESCE(c)) FROM t1;
DROP TABLE t1;
--echo #
--echo # MDEV-14221 Assertion `0' failed in Item::field_type_for_temporal_comparison
--echo #
CREATE TABLE t1 (d DATE);
INSERT INTO t1 VALUES ('1985-05-13'),('1989-12-24');
SELECT d, COUNT(*) FROM t1 GROUP BY d WITH ROLLUP HAVING CASE d WHEN '2017-05-25' THEN 0 ELSE 1 END;
DROP TABLE t1;
--echo #
--echo # End of 10.1 tests

View File

@@ -746,6 +746,17 @@ SELECT * FROM t1;
DROP TABLE t1,t2;
--echo #
--echo # MDEV-10817 CAST(MAX(DATE'2001-01-01') AS TIME) returns a wrong result
--echo #
SELECT CAST(DATE'2001-01-01' AS TIME);
SELECT CAST(MAX(DATE'2001-01-01') AS TIME);
CREATE FUNCTION f1() RETURNS DATE RETURN DATE'2001-01-01';
SELECT CAST(f1() AS TIME);
DROP FUNCTION f1;
--echo #
--echo # End of 10.2 tests
--echo #

View File

@@ -1,3 +1,4 @@
--source include/have_partition.inc
# Save the initial number of concurrent sessions.
--source include/count_sessions.inc

View File

@@ -15,7 +15,7 @@
#define PLUGIN_VERSION 0x104
#define PLUGIN_STR_VERSION "1.4.2"
#define PLUGIN_STR_VERSION "1.4.3"
#define _my_thread_var loc_thread_var
@@ -1118,6 +1118,21 @@ do { \
} while(0)
#define ESC_MAP_SIZE 0x60
static const char esc_map[ESC_MAP_SIZE]=
{
0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, '\'', 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0
};
static char escaped_char(char c)
{
return ((unsigned char ) c) >= ESC_MAP_SIZE ? 0 : esc_map[(unsigned char) c];
}
static void setup_connection_initdb(struct connection_info *cn,
@@ -1324,21 +1339,16 @@ static size_t escape_string(const char *str, unsigned int len,
const char *res_end= result + result_len - 2;
while (len)
{
char esc_c;
if (result >= res_end)
break;
if (*str == '\'')
if ((esc_c= escaped_char(*str)))
{
if (result+1 >= res_end)
break;
*(result++)= '\\';
*(result++)= '\'';
}
else if (*str == '\\')
{
if (result+1 >= res_end)
break;
*(result++)= '\\';
*(result++)= '\\';
*(result++)= esc_c;
}
else if (is_space(*str))
*(result++)= ' ';
@@ -1427,19 +1437,12 @@ static size_t escape_string_hide_passwords(const char *str, unsigned int len,
no_password:
if (result >= res_end)
break;
if (*str == '\'')
if ((b_char= escaped_char(*str)))
{
if (result+1 >= res_end)
break;
*(result++)= '\\';
*(result++)= '\'';
}
else if (*str == '\\')
{
if (result+1 >= res_end)
break;
*(result++)= '\\';
*(result++)= '\\';
*(result++)= b_char;
}
else if (is_space(*str))
*(result++)= ' ';

View File

@@ -46,11 +46,13 @@ static int read_string(File file, uchar**to, size_t length)
engine_name is a LEX_CSTRING, where engine_name->str must point to
a buffer of at least NAME_CHAR_LEN+1 bytes.
If engine_name is 0, then the function will only test if the file is a
view or not
@param[out] is_sequence 1 if table is a SEQUENCE, 0 otherwise
@retval TABLE_TYPE_UNKNOWN error
@retval TABLE_TYPE_TABLE table
@retval TABLE_TYPE_NORMAL table
@retval TABLE_TYPE_SEQUENCE sequence table
@retval TABLE_TYPE_VIEW view
*/
@@ -80,12 +82,26 @@ Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name,
goto err;
}
/*
We return TABLE_TYPE_NORMAL if we can read the .frm file. This allows us
to drop a bad .frm file with DROP TABLE
*/
type= TABLE_TYPE_NORMAL;
if (!is_binary_frm_header(header) || !engine_name)
/* engine_name is 0 if we only want to know if table is view or not */
if (!engine_name)
goto err;
/*
Initialize engine name in case we are not able to find it out
The cast is safe, as engine_name->str points to a usable buffer.
*/
engine_name->length= 0;
((char*) (engine_name->str))[0]= 0;
if (!is_binary_frm_header(header))
goto err;
dbt= header[3];
if (((header[39] >> 4) & 3) == HA_CHOICE_YES)

View File

@@ -5089,8 +5089,13 @@ bool ha_table_exists(THD *thd, const char *db, const char *table_name,
{
char engine_buf[NAME_CHAR_LEN + 1];
LEX_CSTRING engine= { engine_buf, 0 };
Table_type type;
if (dd_frm_type(thd, path, &engine, is_sequence) != TABLE_TYPE_VIEW)
if ((type= dd_frm_type(thd, path, &engine, is_sequence)) ==
TABLE_TYPE_UNKNOWN)
DBUG_RETURN(0);
if (type != TABLE_TYPE_VIEW)
{
plugin_ref p= plugin_lock_by_name(thd, &engine,
MYSQL_STORAGE_ENGINE_PLUGIN);

View File

@@ -3238,7 +3238,8 @@ table_map Item_field::all_used_tables() const
return (get_depended_from() ? OUTER_REF_TABLE_BIT : field->table->map);
}
void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
if (new_parent == get_depended_from())
depended_from= NULL;
@@ -3282,6 +3283,19 @@ void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref)
if (!need_change)
return;
if (!merge)
{
/*
It is transformation without merge.
This field was "outer" for the inner SELECT where it was taken and
moved up.
"Outer" fields uses normal SELECT_LEX context of upper SELECTs for
name resolution, so we can switch everything to it safely.
*/
this->context= &new_parent->context;
return;
}
Name_resolution_context *ctx= new Name_resolution_context();
if (context->select_lex == new_parent)
{
@@ -8698,18 +8712,19 @@ bool Item_outer_ref::fix_fields(THD *thd, Item **reference)
void Item_outer_ref::fix_after_pullout(st_select_lex *new_parent,
Item **ref_arg)
Item **ref_arg, bool merge)
{
if (get_depended_from() == new_parent)
{
*ref_arg= outer_ref;
(*ref_arg)->fix_after_pullout(new_parent, ref_arg);
(*ref_arg)->fix_after_pullout(new_parent, ref_arg, merge);
}
}
void Item_ref::fix_after_pullout(st_select_lex *new_parent, Item **refptr)
void Item_ref::fix_after_pullout(st_select_lex *new_parent, Item **refptr,
bool merge)
{
(*ref)->fix_after_pullout(new_parent, ref);
(*ref)->fix_after_pullout(new_parent, ref, merge);
if (get_depended_from() == new_parent)
depended_from= NULL;
}

View File

@@ -733,7 +733,9 @@ public:
Fix after some tables has been pulled out. Basically re-calculate all
attributes that are dependent on the tables.
*/
virtual void fix_after_pullout(st_select_lex *new_parent, Item **ref) {};
virtual void fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{};
/*
This method should be used in case where we are sure that we do not need
@@ -2760,7 +2762,7 @@ public:
bool send(Protocol *protocol, st_value *buffer);
void reset_field(Field *f);
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
void make_field(THD *thd, Send_field *tmp_field);
int save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field, fast_field_copier optimizer_data);
@@ -3026,6 +3028,17 @@ public:
Field *result_field;
Item_null_result(THD *thd): Item_null(thd), result_field(0) {}
bool is_result_field() { return result_field != 0; }
#if MARIADB_VERSION_ID < 100300
enum_field_types field_type() const
{
return result_field->type();
}
#else
const Type_handler *type_handler() const
{
return result_field->type_handler();
}
#endif
void save_in_result_field(bool no_conversions)
{
save_in_field(result_field, no_conversions);
@@ -4390,7 +4403,7 @@ public:
bool send(Protocol *prot, st_value *buffer);
void make_field(THD *thd, Send_field *field);
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
int save_in_field(Field *field, bool no_conversions);
void save_org_in_field(Field *field, fast_field_copier optimizer_data);
fast_field_copier setup_fast_field_copier(Field *field)
@@ -4698,9 +4711,9 @@ public:
Item *it= ((Item *) item)->real_item();
return orig_item->eq(it, binary_cmp);
}
void fix_after_pullout(st_select_lex *new_parent, Item **refptr)
void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge)
{
orig_item->fix_after_pullout(new_parent, &orig_item);
orig_item->fix_after_pullout(new_parent, &orig_item, merge);
}
int save_in_field(Field *to, bool no_conversions);
const Type_handler *type_handler() const { return orig_item->type_handler(); }
@@ -4969,7 +4982,7 @@ public:
outer_ref->save_org_in_field(result_field, NULL);
}
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
table_map used_tables() const
{
return (*ref)->const_item() ? 0 : OUTER_REF_TABLE_BIT;

View File

@@ -1220,10 +1220,11 @@ bool Item_in_optimizer::is_top_level_item()
}
void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent,
Item **ref, bool merge)
{
/* This will re-calculate attributes of our Item_in_subselect: */
Item_bool_func::fix_after_pullout(new_parent, ref);
Item_bool_func::fix_after_pullout(new_parent, ref, merge);
/* Then, re-calculate not_null_tables_cache: */
eval_not_null_tables(NULL);
@@ -2050,10 +2051,11 @@ bool Item_func_between::count_sargable_conds(void *arg)
}
void Item_func_between::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_func_between::fix_after_pullout(st_select_lex *new_parent,
Item **ref, bool merge)
{
/* This will re-calculate attributes of the arguments */
Item_func_opt_neg::fix_after_pullout(new_parent, ref);
Item_func_opt_neg::fix_after_pullout(new_parent, ref, merge);
/* Then, re-calculate not_null_tables_cache according to our special rules */
eval_not_null_tables(NULL);
}
@@ -2378,10 +2380,11 @@ Item_func_if::eval_not_null_tables(void *opt_arg)
}
void Item_func_if::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_func_if::fix_after_pullout(st_select_lex *new_parent,
Item **ref, bool merge)
{
/* This will re-calculate attributes of the arguments */
Item_func::fix_after_pullout(new_parent, ref);
Item_func::fix_after_pullout(new_parent, ref, merge);
/* Then, re-calculate not_null_tables_cache according to our special rules */
eval_not_null_tables(NULL);
}
@@ -4144,10 +4147,11 @@ Item_func_in::eval_not_null_tables(void *opt_arg)
}
void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_func_in::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
/* This will re-calculate attributes of the arguments */
Item_func_opt_neg::fix_after_pullout(new_parent, ref);
Item_func_opt_neg::fix_after_pullout(new_parent, ref, merge);
/* Then, re-calculate not_null_tables_cache according to our special rules */
eval_not_null_tables(NULL);
}
@@ -4651,7 +4655,8 @@ Item_cond::eval_not_null_tables(void *opt_arg)
}
void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
List_iterator<Item> li(list);
Item *item;
@@ -4664,7 +4669,7 @@ void Item_cond::fix_after_pullout(st_select_lex *new_parent, Item **ref)
while ((item=li++))
{
table_map tmp_table_map;
item->fix_after_pullout(new_parent, li.ref());
item->fix_after_pullout(new_parent, li.ref(), merge);
item= *li.ref();
used_tables_and_const_cache_join(item);

View File

@@ -375,7 +375,7 @@ public:
virtual void get_cache_parameters(List<Item> &parameters);
bool is_top_level_item();
bool eval_not_null_tables(void *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool invisible_mode();
void reset_cache() { cache= NULL; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
@@ -908,7 +908,7 @@ public:
bool fix_length_and_dec_numeric(THD *);
virtual void print(String *str, enum_query_type query_type);
bool eval_not_null_tables(void *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool count_sargable_conds(void *arg);
void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
uint *and_level, table_map usable_tables,
@@ -1144,7 +1144,7 @@ public:
}
const char *func_name() const { return "if"; }
bool eval_not_null_tables(void *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_if>(thd, mem_root, this); }
private:
@@ -2378,7 +2378,7 @@ public:
const char *func_name() const { return "in"; }
enum precedence precedence() const { return CMP_PRECEDENCE; }
bool eval_not_null_tables(void *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool count_sargable_conds(void *arg);
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_in>(thd, mem_root, this); }
@@ -2902,7 +2902,7 @@ public:
list.append(nlist);
}
bool fix_fields(THD *, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
enum Type type() const { return COND_ITEM; }
List<Item>* argument_list() { return &list; }

View File

@@ -406,7 +406,8 @@ Item_func::eval_not_null_tables(void *opt_arg)
}
void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
Item **arg,**arg_end;
@@ -417,7 +418,7 @@ void Item_func::fix_after_pullout(st_select_lex *new_parent, Item **ref)
{
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
(*arg)->fix_after_pullout(new_parent, arg);
(*arg)->fix_after_pullout(new_parent, arg, merge);
Item *item= *arg;
used_tables_and_const_cache_join(item);

View File

@@ -129,7 +129,7 @@ public:
Item_func_or_sum::cleanup();
used_tables_and_const_cache_init();
}
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
void quick_fix_field();
table_map not_null_tables() const;
void update_used_tables()
@@ -2809,6 +2809,13 @@ public:
return sp_result_field->val_decimal(dec_buf);
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
if (execute())
return true;
return sp_result_field->get_date(ltime, fuzzydate);
}
String *val_str(String *str)
{
String buf;

View File

@@ -181,7 +181,8 @@ String *Item_func_inet_str_base::val_str_ascii(String *buffer)
return NULL;
}
String *arg_str= args[0]->val_str(buffer);
StringBuffer<STRING_BUFFER_USUAL_SIZE> tmp;
String *arg_str= args[0]->val_str(&tmp);
if (!arg_str) // Out-of memory happened. The error has been reported.
{ // Or: the underlying field is NULL
null_value= true;
@@ -679,7 +680,7 @@ static void ipv6_to_str(const in6_addr *ipv6, char *str)
@retval true The string has been converted sucessfully.
*/
bool Item_func_inet6_aton::calc_value(String *arg, String *buffer)
bool Item_func_inet6_aton::calc_value(const String *arg, String *buffer)
{
// ipv4-string -> varbinary(4)
// ipv6-string -> varbinary(16)
@@ -719,7 +720,7 @@ bool Item_func_inet6_aton::calc_value(String *arg, String *buffer)
@retval true The string has been converted sucessfully.
*/
bool Item_func_inet6_ntoa::calc_value(String *arg, String *buffer)
bool Item_func_inet6_ntoa::calc_value(const String *arg, String *buffer)
{
if (arg->charset() != &my_charset_bin)
return false;

View File

@@ -105,7 +105,7 @@ public:
virtual String *val_str_ascii(String *buffer);
protected:
virtual bool calc_value(String *arg, String *buffer) = 0;
virtual bool calc_value(const String *arg, String *buffer) = 0;
};
@@ -134,7 +134,7 @@ public:
{ return get_item_copy<Item_func_inet6_aton>(thd, mem_root, this); }
protected:
virtual bool calc_value(String *arg, String *buffer);
virtual bool calc_value(const String *arg, String *buffer);
};
@@ -168,7 +168,7 @@ public:
{ return get_item_copy<Item_func_inet6_ntoa>(thd, mem_root, this); }
protected:
virtual bool calc_value(String *arg, String *buffer);
virtual bool calc_value(const String *arg, String *buffer);
};

View File

@@ -110,13 +110,14 @@ void Item_row::split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
}
void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_row::fix_after_pullout(st_select_lex *new_parent, Item **ref,
bool merge)
{
used_tables_and_const_cache_init();
not_null_tables_cache= 0;
for (uint i= 0; i < arg_count; i++)
{
args[i]->fix_after_pullout(new_parent, &args[i]);
args[i]->fix_after_pullout(new_parent, &args[i], merge);
used_tables_and_const_cache_join(args[i]);
not_null_tables_cache|= args[i]->not_null_tables();
}

View File

@@ -81,7 +81,7 @@ public:
return 0;
};
bool fix_fields(THD *thd, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
void cleanup();
void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields, uint flags);

View File

@@ -400,8 +400,7 @@ public:
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_replace"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_regexp_replace>(thd, mem_root, this); }
Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0;}
};
@@ -423,8 +422,7 @@ public:
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_substr"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_regexp_substr>(thd, mem_root, this); }
Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
};

View File

@@ -452,7 +452,8 @@ bool Item_subselect::mark_as_dependent(THD *thd, st_select_lex *select,
OUTER_REF_TABLE_BIT.
*/
void Item_subselect::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_subselect::fix_after_pullout(st_select_lex *new_parent,
Item **ref, bool merge)
{
recalc_used_tables(new_parent, TRUE);
parent_select= new_parent;
@@ -1160,7 +1161,8 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
/*
as far as we moved content to upper level we have to fix dependences & Co
*/
substitution->fix_after_pullout(select_lex->outer_select(), &substitution);
substitution->fix_after_pullout(select_lex->outer_select(),
&substitution, TRUE);
}
DBUG_RETURN(false);
}
@@ -2937,7 +2939,7 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
goto out;
}
}
outer_exp->fix_after_pullout(unit->outer_select(), &outer_exp);
outer_exp->fix_after_pullout(unit->outer_select(), &outer_exp, FALSE);
outer_exp->update_used_tables();
outer.push_back(outer_exp, thd->mem_root);
}
@@ -3318,10 +3320,11 @@ err:
}
void Item_in_subselect::fix_after_pullout(st_select_lex *new_parent, Item **ref)
void Item_in_subselect::fix_after_pullout(st_select_lex *new_parent,
Item **ref, bool merge)
{
left_expr->fix_after_pullout(new_parent, &left_expr);
Item_subselect::fix_after_pullout(new_parent, ref);
left_expr->fix_after_pullout(new_parent, &left_expr, merge);
Item_subselect::fix_after_pullout(new_parent, ref, merge);
used_tables_cache |= left_expr->used_tables();
}

View File

@@ -183,7 +183,7 @@ public:
}
bool fix_fields(THD *thd, Item **ref);
bool mark_as_dependent(THD *thd, st_select_lex *select, Item *item);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
void recalc_used_tables(st_select_lex *new_parent, bool after_pullout);
virtual bool exec();
/*
@@ -624,7 +624,7 @@ public:
enum precedence precedence() const { return CMP_PRECEDENCE; }
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool const_item() const
{
return Item_subselect::const_item() && left_expr->const_item();

View File

@@ -2019,6 +2019,18 @@ void Item_sum_hybrid::clear()
null_value= 1;
}
bool
Item_sum_hybrid::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
DBUG_ASSERT(fixed == 1);
if (null_value)
return true;
bool retval= value->get_date(ltime, fuzzydate);
if ((null_value= value->null_value))
DBUG_ASSERT(retval == true);
return retval;
}
double Item_sum_hybrid::val_real()
{
DBUG_ASSERT(fixed == 1);

View File

@@ -1034,6 +1034,7 @@ protected:
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
void reset_field();
String *val_str(String *);
const Type_handler *real_type_handler() const

View File

@@ -1642,7 +1642,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
{
tl->jtbm_table_no= table_no;
Item *dummy= tl->jtbm_subselect;
tl->jtbm_subselect->fix_after_pullout(parent_lex, &dummy);
tl->jtbm_subselect->fix_after_pullout(parent_lex, &dummy, true);
DBUG_ASSERT(dummy == tl->jtbm_subselect);
}
SELECT_LEX *old_sl= tl->select_lex;
@@ -1783,7 +1783,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
Walk through sj nest's WHERE and ON expressions and call
item->fix_table_changes() for all items.
*/
sj_nest->sj_on_expr->fix_after_pullout(parent_lex, &sj_nest->sj_on_expr);
sj_nest->sj_on_expr->fix_after_pullout(parent_lex, &sj_nest->sj_on_expr,
TRUE);
fix_list_after_tbl_changes(parent_lex, &sj_nest->nested_join->join_list);
@@ -1942,7 +1943,7 @@ static bool convert_subq_to_jtbm(JOIN *parent_join,
DBUG_ASSERT(parent_join->table_count < MAX_TABLES);
Item *conds= hash_sj_engine->semi_join_conds;
conds->fix_after_pullout(parent_lex, &conds);
conds->fix_after_pullout(parent_lex, &conds, TRUE);
DBUG_EXECUTE("where", print_where(conds,"SJ-EXPR", QT_ORDINARY););
@@ -1994,7 +1995,7 @@ void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist)
while ((table= it++))
{
if (table->on_expr)
table->on_expr->fix_after_pullout(new_parent, &table->on_expr);
table->on_expr->fix_after_pullout(new_parent, &table->on_expr, TRUE);
if (table->nested_join)
fix_list_after_tbl_changes(new_parent, &table->nested_join->join_list);
}

View File

@@ -349,7 +349,10 @@ void With_element::check_dependencies_in_select(st_select_lex *sl,
/* Now look for the dependencies in the subqueries of sl */
st_select_lex_unit *inner_unit= sl->first_inner_unit();
for (; inner_unit; inner_unit= inner_unit->next_unit())
check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map);
{
if (!inner_unit->with_element)
check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map);
}
}
@@ -837,7 +840,6 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
with_table->next_global= spec_tables;
}
res= &lex->unit;
res->set_with_clause(owner);
lex->unit.include_down(with_table->select_lex);
lex->unit.set_slave(with_select);
@@ -846,6 +848,8 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
insert_chain_before(
(st_select_lex_node **) &(old_lex->all_selects_list),
with_select));
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
res= NULL;
lex_end(lex);
err:
if (arena)
@@ -989,14 +993,18 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table)
and it was unsuccesful. Yet for units cloned from the spec it has not
been done yet.
*/
if (with_elem && sl->master_unit() == with_elem->spec)
With_clause *attached_with_clause=sl->get_with_clause();
if (attached_with_clause &&
(found= attached_with_clause->find_table_def(table, NULL)))
break;
With_clause *with_clause=sl->get_with_clause();
if (with_clause)
if (with_elem)
{
With_element *barrier= with_clause->with_recursive ? NULL : with_elem;
if ((found= with_clause->find_table_def(table, barrier)))
With_clause *containing_with_clause= with_elem->get_owner();
With_element *barrier= containing_with_clause->with_recursive ?
NULL : with_elem;
if ((found= containing_with_clause->find_table_def(table, barrier)))
break;
sl= sl->master_unit()->outer_select();
}
master_unit= sl->master_unit();
/* Do not look for the table's definition beyond the scope of the view */

View File

@@ -468,7 +468,8 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
// Update used tables cache according to new table map
if (derived->on_expr)
{
derived->on_expr->fix_after_pullout(parent_lex, &derived->on_expr);
derived->on_expr->fix_after_pullout(parent_lex, &derived->on_expr,
TRUE);
fix_list_after_tbl_changes(parent_lex, &derived->nested_join->join_list);
}
}
@@ -641,7 +642,8 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
SELECT_LEX_UNIT *unit= derived->get_unit();
DBUG_ENTER("mysql_derived_prepare");
bool res= FALSE;
DBUG_PRINT("enter", ("unit %p", unit));
DBUG_PRINT("enter", ("unit: %p table_list: %p Alias '%s'",
unit, derived, derived->alias));
if (!unit)
DBUG_RETURN(FALSE);

View File

@@ -4168,7 +4168,8 @@ buf_page_get_gen(
ulint retries = 0;
buf_pool_t* buf_pool = buf_pool_get(page_id);
ut_ad(mtr->is_active());
ut_ad((mtr == NULL) == (mode == BUF_EVICT_IF_IN_POOL));
ut_ad(!mtr || mtr->is_active());
ut_ad((rw_latch == RW_S_LATCH)
|| (rw_latch == RW_X_LATCH)
|| (rw_latch == RW_SX_LATCH)
@@ -4180,29 +4181,31 @@ buf_page_get_gen(
#ifdef UNIV_DEBUG
switch (mode) {
case BUF_EVICT_IF_IN_POOL:
/* After DISCARD TABLESPACE, the tablespace would not exist,
but in IMPORT TABLESPACE, PageConverter::operator() must
replace any old pages, which were not evicted during DISCARD.
Skip the assertion on space_page_size. */
break;
default:
ut_error;
case BUF_GET_NO_LATCH:
ut_ad(rw_latch == RW_NO_LATCH);
break;
/* fall through */
case BUF_GET:
case BUF_GET_IF_IN_POOL:
case BUF_PEEK_IF_IN_POOL:
case BUF_GET_IF_IN_POOL_OR_WATCH:
case BUF_GET_POSSIBLY_FREED:
break;
default:
ut_error;
bool found;
const page_size_t& space_page_size
= fil_space_get_page_size(page_id.space(), &found);
ut_ad(found);
ut_ad(page_size.equals_to(space_page_size));
}
bool found;
const page_size_t& space_page_size
= fil_space_get_page_size(page_id.space(), &found);
ut_ad(found);
ut_ad(page_size.equals_to(space_page_size));
#endif /* UNIV_DEBUG */
ut_ad(!ibuf_inside(mtr)
ut_ad(!mtr || !ibuf_inside(mtr)
|| ibuf_page_low(page_id, page_size, FALSE, file, line, NULL));
buf_pool->stat.n_page_gets++;
@@ -4290,13 +4293,15 @@ loop:
rw_lock_x_unlock(hash_lock);
}
if (mode == BUF_GET_IF_IN_POOL
|| mode == BUF_PEEK_IF_IN_POOL
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
switch (mode) {
case BUF_GET_IF_IN_POOL:
case BUF_GET_IF_IN_POOL_OR_WATCH:
case BUF_PEEK_IF_IN_POOL:
case BUF_EVICT_IF_IN_POOL:
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X));
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_S));
#endif /* UNIV_SYNC_DEBUG */
return(NULL);
}
@@ -4390,8 +4395,10 @@ loop:
got_block:
if (mode == BUF_GET_IF_IN_POOL || mode == BUF_PEEK_IF_IN_POOL) {
switch (mode) {
case BUF_GET_IF_IN_POOL:
case BUF_PEEK_IF_IN_POOL:
case BUF_EVICT_IF_IN_POOL:
buf_page_t* fix_page = &fix_block->page;
BPageMutex* fix_mutex = buf_page_get_mutex(fix_page);
mutex_enter(fix_mutex);
@@ -4423,6 +4430,20 @@ got_block:
os_thread_sleep(WAIT_FOR_WRITE);
goto loop;
}
if (UNIV_UNLIKELY(mode == BUF_EVICT_IF_IN_POOL)) {
evict_from_pool:
ut_ad(!fix_block->page.oldest_modification);
buf_pool_mutex_enter(buf_pool);
buf_block_unfix(fix_block);
if (!buf_LRU_free_page(&fix_block->page, true)) {
ut_ad(0);
}
buf_pool_mutex_exit(buf_pool);
return(NULL);
}
break;
case BUF_BLOCK_ZIP_PAGE:
@@ -4455,6 +4476,10 @@ got_block:
goto loop;
}
if (UNIV_UNLIKELY(mode == BUF_EVICT_IF_IN_POOL)) {
goto evict_from_pool;
}
/* Buffer-fix the block so that it cannot be evicted
or relocated while we are attempting to allocate an
uncompressed page. */

View File

@@ -3821,24 +3821,16 @@ FlushObserver::notify_remove(
void
FlushObserver::flush()
{
buf_remove_t buf_remove;
if (m_interrupted) {
buf_remove = BUF_REMOVE_FLUSH_NO_WRITE;
} else {
buf_remove = BUF_REMOVE_FLUSH_WRITE;
if (m_stage != NULL) {
ulint pages_to_flush =
buf_flush_get_dirty_pages_count(
m_space_id, this);
m_stage->begin_phase_flush(pages_to_flush);
}
if (!m_interrupted && m_stage) {
m_stage->begin_phase_flush(buf_flush_get_dirty_pages_count(
m_space_id, this));
}
/* Flush or remove dirty pages. */
buf_LRU_flush_or_remove_pages(m_space_id, buf_remove, m_trx);
/* MDEV-14317 FIXME: Discard all changes to only those pages
that will be freed by the clean-up of the ALTER operation.
(Maybe, instead of buf_pool->flush_list, use a dedicated list
for pages on which redo logging has been disabled.) */
buf_LRU_flush_or_remove_pages(m_space_id, m_trx);
/* Wait for all dirty pages were flushed. */
for (ulint i = 0; i < srv_buf_pool_instances; i++) {

View File

@@ -586,8 +586,8 @@ rescan:
/* If flush observer is NULL, flush page for space id,
or flush page for flush observer. */
if ((observer != NULL && observer != bpage->flush_observer)
|| (observer == NULL && id != bpage->id.space())) {
if (observer ? (observer != bpage->flush_observer)
: (id != bpage->id.space())) {
/* Skip this block, as it does not belong to
the target space. */
@@ -657,24 +657,27 @@ rescan:
return(all_freed ? DB_SUCCESS : DB_FAIL);
}
/******************************************************************//**
Remove or flush all the dirty pages that belong to a given tablespace
/** Remove or flush all the dirty pages that belong to a given tablespace
inside a specific buffer pool instance. The pages will remain in the LRU
list and will be evicted from the LRU list as they age and move towards
the tail of the LRU list. */
the tail of the LRU list.
@param[in,out] buf_pool buffer pool
@param[in] id tablespace identifier
@param[in] observer flush observer,
or NULL if the files should not be written to
@param[in] trx transaction (to check for interrupt),
or NULL if the files should not be written to
*/
static
void
buf_flush_dirty_pages(
/*==================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint id, /*!< in: space id */
FlushObserver* observer, /*!< in: flush observer */
bool flush, /*!< in: flush to disk if true otherwise
remove the pages without flushing */
const trx_t* trx) /*!< to check if the operation must
be interrupted */
buf_pool_t* buf_pool,
ulint id,
FlushObserver* observer,
const trx_t* trx)
{
dberr_t err;
bool flush = trx != NULL;
do {
buf_pool_mutex_enter(buf_pool);
@@ -708,238 +711,30 @@ buf_flush_dirty_pages(
|| buf_pool_get_dirty_pages_count(buf_pool, id, observer) == 0);
}
/******************************************************************//**
Remove all pages that belong to a given tablespace inside a specific
buffer pool instance when we are DISCARDing the tablespace. */
static
/** Empty the flush list for all pages belonging to a tablespace.
@param[in] id tablespace identifier
@param[in] trx transaction, for checking for user interrupt;
or NULL if nothing is to be written
@param[in] drop_ahi whether to drop the adaptive hash index */
void
buf_LRU_remove_all_pages(
/*=====================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint id) /*!< in: space id */
{
buf_page_t* bpage;
ibool all_freed;
scan_again:
buf_pool_mutex_enter(buf_pool);
all_freed = TRUE;
for (bpage = UT_LIST_GET_LAST(buf_pool->LRU);
bpage != NULL;
/* No op */) {
rw_lock_t* hash_lock;
buf_page_t* prev_bpage;
BPageMutex* block_mutex;
ut_a(buf_page_in_file(bpage));
ut_ad(bpage->in_LRU_list);
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
/* bpage->id.space() and bpage->io_fix are protected by
buf_pool->mutex and the block_mutex. It is safe to check
them while holding buf_pool->mutex only. */
if (bpage->id.space() != id) {
/* Skip this block, as it does not belong to
the space that is being invalidated. */
goto next_page;
} else if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
/* We cannot remove this page during this scan
yet; maybe the system is currently reading it
in, or flushing the modifications to the file */
all_freed = FALSE;
goto next_page;
} else {
hash_lock = buf_page_hash_lock_get(buf_pool, bpage->id);
rw_lock_x_lock(hash_lock);
block_mutex = buf_page_get_mutex(bpage);
mutex_enter(block_mutex);
if (bpage->buf_fix_count > 0) {
mutex_exit(block_mutex);
rw_lock_x_unlock(hash_lock);
/* We cannot remove this page during
this scan yet; maybe the system is
currently reading it in, or flushing
the modifications to the file */
all_freed = FALSE;
goto next_page;
}
}
ut_ad(mutex_own(block_mutex));
DBUG_PRINT("ib_buf", ("evict page %u:%u"
" state %u",
bpage->id.space(),
bpage->id.page_no(),
bpage->state));
#ifdef BTR_CUR_HASH_ADAPT
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
/* Do nothing, because the adaptive hash index
covers uncompressed pages only. */
} else if (((buf_block_t*) bpage)->index) {
buf_pool_mutex_exit(buf_pool);
rw_lock_x_unlock(hash_lock);
mutex_exit(block_mutex);
/* Note that the following call will acquire
and release block->lock X-latch.
Note that the table cannot be evicted during
the execution of ALTER TABLE...DISCARD TABLESPACE
because MySQL is keeping the table handle open. */
btr_search_drop_page_hash_when_freed(
bpage->id, bpage->size);
goto scan_again;
} else {
/* This debug check uses a dirty read that could
theoretically cause false positives while
buf_pool_clear_hash_index() is executing,
if the writes to block->index=NULL and
block->n_pointers=0 are reordered.
(Other conflicting access paths to the adaptive hash
index should not be possible, because when a
tablespace is being discarded or dropped, there must
be no concurrect access to the contained tables.) */
assert_block_ahi_empty((buf_block_t*) bpage);
}
#endif /* BTR_CUR_HASH_ADAPT */
if (bpage->oldest_modification != 0) {
buf_flush_remove(bpage);
}
ut_ad(!bpage->in_flush_list);
/* Remove from the LRU list. */
if (buf_LRU_block_remove_hashed(bpage, true)) {
buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
} else {
ut_ad(block_mutex == &buf_pool->zip_mutex);
}
ut_ad(!mutex_own(block_mutex));
/* buf_LRU_block_remove_hashed() releases the hash_lock */
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X));
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_S));
next_page:
bpage = prev_bpage;
}
buf_pool_mutex_exit(buf_pool);
if (!all_freed) {
os_thread_sleep(20000);
goto scan_again;
}
}
/******************************************************************//**
Remove pages belonging to a given tablespace inside a specific
buffer pool instance when we are deleting the data file(s) of that
tablespace. The pages still remain a part of LRU and are evicted from
the list as they age towards the tail of the LRU only if buf_remove
is BUF_REMOVE_FLUSH_NO_WRITE. */
static
void
buf_LRU_remove_pages(
/*=================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint id, /*!< in: space id */
buf_remove_t buf_remove, /*!< in: remove or flush strategy */
const trx_t* trx) /*!< to check if the operation must
be interrupted */
buf_LRU_flush_or_remove_pages(ulint id, const trx_t* trx, bool drop_ahi)
{
FlushObserver* observer = (trx == NULL) ? NULL : trx->flush_observer;
/* Pages in the system tablespace must never be discarded. */
ut_ad(id || trx);
switch (buf_remove) {
case BUF_REMOVE_ALL_NO_WRITE:
buf_LRU_remove_all_pages(buf_pool, id);
break;
case BUF_REMOVE_FLUSH_NO_WRITE:
/* Pass trx as NULL to avoid interruption check. */
buf_flush_dirty_pages(buf_pool, id, observer, false, NULL);
break;
case BUF_REMOVE_FLUSH_WRITE:
buf_flush_dirty_pages(buf_pool, id, observer, true, trx);
if (observer == NULL) {
/* Ensure that all asynchronous IO is completed. */
os_aio_wait_until_no_pending_writes();
fil_flush(id);
}
break;
}
}
/******************************************************************//**
Flushes all dirty pages or removes all pages belonging
to a given tablespace. A PROBLEM: if readahead is being started, what
guarantees that it will not try to read in pages after this operation
has completed? */
void
buf_LRU_flush_or_remove_pages(
/*==========================*/
ulint id, /*!< in: space id */
buf_remove_t buf_remove, /*!< in: remove or flush strategy */
const trx_t* trx) /*!< to check if the operation must
be interrupted */
{
ulint i;
/* Before we attempt to drop pages one by one we first
attempt to drop page hash index entries in batches to make
it more efficient. The batching attempt is a best effort
attempt and does not guarantee that all pages hash entries
will be dropped. We get rid of remaining page hash entries
one by one below. */
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
#ifdef BTR_CUR_HASH_ADAPT
switch (buf_remove) {
case BUF_REMOVE_ALL_NO_WRITE:
for (ulint i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool = buf_pool_from_array(i);
if (drop_ahi) {
buf_LRU_drop_page_hash_for_tablespace(buf_pool, id);
break;
case BUF_REMOVE_FLUSH_NO_WRITE:
/* It is a DROP TABLE for a single table
tablespace. No AHI entries exist because
we already dealt with them when freeing up
extents. */
case BUF_REMOVE_FLUSH_WRITE:
/* We allow read-only queries against the
table, there is no need to drop the AHI entries. */
break;
}
#endif /* BTR_CUR_HASH_ADAPT */
buf_LRU_remove_pages(buf_pool, id, buf_remove, trx);
buf_flush_dirty_pages(buf_pool, id, observer, trx);
}
if (trx && !observer && !trx_is_interrupted(trx)) {
/* Ensure that all asynchronous IO is completed. */
os_aio_wait_until_no_pending_writes();
fil_flush(id);
}
}

View File

@@ -1641,7 +1641,7 @@ dict_table_rename_in_cache(
return(DB_OUT_OF_MEMORY);
}
fil_delete_tablespace(table->space, BUF_REMOVE_ALL_NO_WRITE);
fil_delete_tablespace(table->space, true);
/* Delete any temp file hanging around. */
if (os_file_status(filepath, &exists, &ftype)

View File

@@ -2449,7 +2449,7 @@ fil_recreate_tablespace(
/* Step-1: Invalidate buffer pool pages belonging to the tablespace
to re-create. */
buf_LRU_flush_or_remove_pages(space_id, BUF_REMOVE_ALL_NO_WRITE, 0);
buf_LRU_flush_or_remove_pages(space_id, NULL);
/* Remove all insert buffer entries for the tablespace */
ibuf_delete_for_discarded_space(space_id);
@@ -2907,7 +2907,7 @@ fil_close_tablespace(
completely and permanently. The flag stop_new_ops also prevents
fil_flush() from being applied to this tablespace. */
buf_LRU_flush_or_remove_pages(id, BUF_REMOVE_FLUSH_WRITE, trx);
buf_LRU_flush_or_remove_pages(id, trx);
/* If the free is successful, the X lock will be released before
the space memory data structure is freed. */
@@ -2959,17 +2959,12 @@ fil_table_accessible(const dict_table_t* table)
}
}
/** Deletes an IBD tablespace, either general or single-table.
The tablespace must be cached in the memory cache. This will delete the
datafile, fil_space_t & fil_node_t entries from the file_system_t cache.
@param[in] space_id Tablespace id
@param[in] buf_remove Specify the action to take on the pages
for this table in the buffer pool.
@return DB_SUCCESS or error */
/** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier
@param[in] drop_ahi whether to drop the adaptive hash index
@return DB_SUCCESS or error */
dberr_t
fil_delete_tablespace(
ulint id,
buf_remove_t buf_remove)
fil_delete_tablespace(ulint id, bool drop_ahi)
{
char* path = 0;
fil_space_t* space = 0;
@@ -3012,7 +3007,7 @@ fil_delete_tablespace(
To deal with potential read requests, we will check the
::stop_new_ops flag in fil_io(). */
buf_LRU_flush_or_remove_pages(id, buf_remove, 0);
buf_LRU_flush_or_remove_pages(id, NULL, drop_ahi);
/* If it is a delete then also delete any generated files, otherwise
when we drop the database the remove directory will fail. */
@@ -3103,7 +3098,7 @@ fil_truncate_tablespace(
/* Step-2: Invalidate buffer pool pages belonging to the tablespace
to re-create. Remove all insert buffer entries for the tablespace */
buf_LRU_flush_or_remove_pages(space_id, BUF_REMOVE_ALL_NO_WRITE, 0);
buf_LRU_flush_or_remove_pages(space_id, NULL);
/* Step-3: Truncate the tablespace and accordingly update
the fil_space_t handler that is used to access this tablespace. */
@@ -3199,7 +3194,7 @@ fil_reinit_space_header_for_table(
from disabling AHI during the scan */
btr_search_s_lock_all();
DEBUG_SYNC_C("buffer_pool_scan");
buf_LRU_flush_or_remove_pages(id, BUF_REMOVE_ALL_NO_WRITE, 0);
buf_LRU_flush_or_remove_pages(id, NULL);
btr_search_s_unlock_all();
row_mysql_lock_data_dictionary(trx);
@@ -3292,7 +3287,7 @@ fil_discard_tablespace(
{
dberr_t err;
switch (err = fil_delete_tablespace(id, BUF_REMOVE_ALL_NO_WRITE)) {
switch (err = fil_delete_tablespace(id, true)) {
case DB_SUCCESS:
break;
@@ -4348,8 +4343,19 @@ fil_ibd_discover(
/* Look for a remote file-per-table tablespace. */
df_rem_per.set_name(db);
if (df_rem_per.open_link_file() == DB_SUCCESS) {
switch (srv_operation) {
case SRV_OPERATION_BACKUP:
case SRV_OPERATION_RESTORE_DELTA:
ut_ad(0);
break;
case SRV_OPERATION_RESTORE_EXPORT:
case SRV_OPERATION_RESTORE:
break;
case SRV_OPERATION_NORMAL:
df_rem_per.set_name(db);
if (df_rem_per.open_link_file() != DB_SUCCESS) {
break;
}
/* An ISL file was found with contents. */
if (df_rem_per.open_read_only(false) != DB_SUCCESS
@@ -4439,6 +4445,18 @@ fil_ibd_load(
return(FIL_LOAD_OK);
}
if (srv_operation == SRV_OPERATION_RESTORE) {
/* Replace absolute DATA DIRECTORY file paths with
short names relative to the backup directory. */
if (const char* name = strrchr(filename, OS_PATH_SEPARATOR)) {
while (--name > filename
&& *name != OS_PATH_SEPARATOR);
if (name > filename) {
filename = name + 1;
}
}
}
Datafile file;
file.set_filepath(filename);
file.open_read_only(false);

View File

@@ -20217,7 +20217,7 @@ wsrep_innobase_kill_one_trx(
wsrep_thd_awake(thd, signal);
} else {
/* abort currently executing query */
DBUG_PRINT("wsrep",("sending KILL_QUERY to: %ld",
DBUG_PRINT("wsrep",("sending KILL_QUERY to: %lu",
thd_get_thread_id(thd)));
WSREP_DEBUG("kill query for: %ld",
thd_get_thread_id(thd));
@@ -20361,7 +20361,8 @@ wsrep_fake_trx_id(
mutex_enter(&trx_sys->mutex);
trx_id_t trx_id = trx_sys_get_new_trx_id();
mutex_exit(&trx_sys->mutex);
WSREP_DEBUG("innodb fake trx id: %lu thd: %s", trx_id, wsrep_thd_query(thd));
WSREP_DEBUG("innodb fake trx id: " TRX_ID_FMT " thd: %s",
trx_id, wsrep_thd_query(thd));
wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id);
}

View File

@@ -4962,21 +4962,36 @@ ibuf_check_bitmap_on_import(
const trx_t* trx, /*!< in: transaction */
ulint space_id) /*!< in: tablespace identifier */
{
ulint size;
ulint page_no;
ut_ad(space_id);
ut_ad(trx->mysql_thd);
bool found;
const page_size_t& page_size
= fil_space_get_page_size(space_id, &found);
if (!found) {
FilSpace space(space_id);
if (!space()) {
return(DB_TABLE_NOT_FOUND);
}
size = fil_space_get_size(space_id);
const page_size_t page_size(space->flags);
/* fil_space_t::size and fil_space_t::free_limit would still be 0
at this point. So, we will have to read page 0. */
ut_ad(!space->free_limit);
ut_ad(!space->size);
mtr_t mtr;
ulint size;
mtr.start();
if (buf_block_t* sp = buf_page_get(page_id_t(space_id, 0), page_size,
RW_S_LATCH, &mtr)) {
size = std::min(
mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ sp->frame),
mach_read_from_4(FSP_HEADER_OFFSET + FSP_SIZE
+ sp->frame));
} else {
size = 0;
}
mtr.commit();
if (size == 0) {
return(DB_TABLE_NOT_FOUND);
@@ -4991,7 +5006,6 @@ ibuf_check_bitmap_on_import(
the space, as usual. */
for (page_no = 0; page_no < size; page_no += page_size.physical()) {
mtr_t mtr;
page_t* bitmap_page;
ulint i;

View File

@@ -65,6 +65,7 @@ struct fil_addr_t;
#define BUF_GET_POSSIBLY_FREED 16
/*!< Like BUF_GET, but do not mind
if the file page has been freed. */
#define BUF_EVICT_IF_IN_POOL 20 /*!< evict a clean block if found */
/* @} */
/** @name Modes for buf_page_get_known_nowait */
/* @{ */

View File

@@ -50,18 +50,14 @@ These are low-level functions
/** Minimum LRU list length for which the LRU_old pointer is defined */
#define BUF_LRU_OLD_MIN_LEN 512 /* 8 megabytes of 16k pages */
/******************************************************************//**
Flushes all dirty pages or removes all pages belonging
to a given tablespace. A PROBLEM: if readahead is being started, what
guarantees that it will not try to read in pages after this operation
has completed? */
/** Empty the flush list for all pages belonging to a tablespace.
@param[in] id tablespace identifier
@param[in] trx transaction, for checking for user interrupt;
or NULL if nothing is to be written
@param[in] drop_ahi whether to drop the adaptive hash index */
UNIV_INTERN
void
buf_LRU_flush_or_remove_pages(
/*==========================*/
ulint id, /*!< in: space id */
buf_remove_t buf_remove, /*!< in: remove or flush strategy */
const trx_t* trx); /*!< to check if the operation must
be interrupted */
buf_LRU_flush_or_remove_pages(ulint id, const trx_t* trx, bool drop_ahi=false);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/********************************************************************//**

View File

@@ -59,17 +59,6 @@ enum buf_flush_t {
BUF_FLUSH_N_TYPES /*!< index of last element + 1 */
};
/** Algorithm to remove the pages for a tablespace from the buffer pool.
See buf_LRU_flush_or_remove_pages(). */
enum buf_remove_t {
BUF_REMOVE_ALL_NO_WRITE, /*!< Remove all pages from the buffer
pool, don't write or sync to disk */
BUF_REMOVE_FLUSH_NO_WRITE, /*!< Remove only, from the flush list,
don't write or sync to disk */
BUF_REMOVE_FLUSH_WRITE /*!< Flush dirty pages to disk only
don't remove from the buffer pool */
};
/** Flags for io_fix types */
enum buf_io_fix {
BUF_IO_NONE = 0, /**< no pending I/O */

View File

@@ -929,17 +929,12 @@ bool
fil_table_accessible(const dict_table_t* table)
MY_ATTRIBUTE((warn_unused_result, nonnull));
/** Deletes an IBD tablespace, either general or single-table.
The tablespace must be cached in the memory cache. This will delete the
datafile, fil_space_t & fil_node_t entries from the file_system_t cache.
@param[in] space_id Tablespace id
@param[in] buf_remove Specify the action to take on the pages
for this table in the buffer pool.
@return true if success */
/** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier
@param[in] drop_ahi whether to drop the adaptive hash index
@return DB_SUCCESS or error */
dberr_t
fil_delete_tablespace(
ulint id,
buf_remove_t buf_remove);
fil_delete_tablespace(ulint id, bool drop_ahi = false);
/** Truncate the tablespace to needed size.
@param[in] space_id id of tablespace to truncate

View File

@@ -1537,18 +1537,16 @@ PageConverter::PageConverter(
:
AbstractCallback(trx),
m_cfg(cfg),
m_index(cfg->m_indexes),
m_current_lsn(log_get_lsn()),
m_page_zip_ptr(0),
m_heap(0) UNIV_NOTHROW
m_rec_iter(),
m_offsets_(), m_offsets(m_offsets_),
m_heap(0),
m_cluster_index(dict_table_get_first_index(cfg->m_table)) UNIV_NOTHROW
{
m_index = m_cfg->m_indexes;
m_current_lsn = log_get_lsn();
ut_a(m_current_lsn > 0);
m_offsets = m_offsets_;
rec_offs_init(m_offsets_);
m_cluster_index = dict_table_get_first_index(m_cfg->m_table);
}
/** Adjust the BLOB reference for a single column that is externally stored
@@ -2008,7 +2006,7 @@ PageConverter::operator() (
we can work on them */
if ((err = update_page(block, page_type)) != DB_SUCCESS) {
return(err);
break;
}
/* Note: For compressed pages this function will write to the
@@ -2047,9 +2045,15 @@ PageConverter::operator() (
<< " at offset " << offset
<< " looks corrupted in file " << m_filepath;
return(DB_CORRUPTION);
err = DB_CORRUPTION;
}
/* If we already had and old page with matching number
in the buffer pool, evict it now, because
we no longer evict the pages on DISCARD TABLESPACE. */
buf_page_get_gen(block->page.id, get_page_size(),
RW_NO_LATCH, NULL, BUF_EVICT_IF_IN_POOL,
__FILE__, __LINE__, NULL, NULL);
return(err);
}
@@ -3649,8 +3653,7 @@ row_import_for_mysql(
The only dirty pages generated should be from the pessimistic purge
of delete marked records that couldn't be purged in Phase I. */
buf_LRU_flush_or_remove_pages(
prebuilt->table->space, BUF_REMOVE_FLUSH_WRITE, trx);
buf_LRU_flush_or_remove_pages(prebuilt->table->space, trx);
if (trx_is_interrupted(trx)) {
ib::info() << "Phase III - Flush interrupted";

View File

@@ -2505,10 +2505,7 @@ err_exit:
/* We already have .ibd file here. it should be deleted. */
if (dict_table_is_file_per_table(table)
&& fil_delete_tablespace(
table->space,
BUF_REMOVE_FLUSH_NO_WRITE)
!= DB_SUCCESS) {
&& fil_delete_tablespace(table->space) != DB_SUCCESS) {
ib::error() << "Not able to delete tablespace "
<< table->space << " of table "
@@ -3175,9 +3172,6 @@ row_discard_tablespace(
4) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0,
we do not allow the discard. */
/* Play safe and remove all insert buffer entries, though we should
have removed them already when DISCARD TABLESPACE was called */
ibuf_delete_for_discarded_space(table->space);
table_id_t new_id;
@@ -3542,8 +3536,7 @@ row_drop_single_table_tablespace(
ib::info() << "Removed datafile " << filepath
<< " for table " << tablename;
} else if (fil_delete_tablespace(space_id, BUF_REMOVE_FLUSH_NO_WRITE)
!= DB_SUCCESS) {
} else if (fil_delete_tablespace(space_id) != DB_SUCCESS) {
ib::error() << "We removed the InnoDB internal data"
" dictionary entry of table " << tablename

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -536,8 +537,7 @@ row_quiesce_table_start(
}
if (!trx_is_interrupted(trx)) {
buf_LRU_flush_or_remove_pages(
table->space, BUF_REMOVE_FLUSH_WRITE, trx);
buf_LRU_flush_or_remove_pages(table->space, trx);
if (trx_is_interrupted(trx)) {

View File

@@ -1100,21 +1100,22 @@ srv_undo_tablespaces_init(bool create_new_db)
mtr_commit(&mtr);
/* Step-2: Flush the dirty pages from the buffer pool. */
trx_t* trx = trx_allocate_for_background();
for (undo::undo_spaces_t::const_iterator it
= undo::Truncate::s_fix_up_spaces.begin();
it != undo::Truncate::s_fix_up_spaces.end();
++it) {
buf_LRU_flush_or_remove_pages(
TRX_SYS_SPACE, BUF_REMOVE_FLUSH_WRITE, NULL);
buf_LRU_flush_or_remove_pages(TRX_SYS_SPACE, trx);
buf_LRU_flush_or_remove_pages(
*it, BUF_REMOVE_FLUSH_WRITE, NULL);
buf_LRU_flush_or_remove_pages(*it, trx);
/* Remove the truncate redo log file. */
undo::Truncate undo_trunc;
undo_trunc.done_logging(*it);
}
trx_free_for_background(trx);
}
return(DB_SUCCESS);

View File

@@ -1,11 +1,14 @@
DROP TABLE IF EXISTS t1;
connect con1,localhost,root,,;
connect con2,localhost,root,,;
connection con1;
CREATE TABLE t1 (id INT, value int, PRIMARY KEY (id), INDEX (value)) ENGINE=RocksDB;
INSERT INTO t1 VALUES (1,1);
select variable_value into @p from information_schema.global_status where variable_name='rocksdb_number_sst_entry_put';
select variable_value into @s from information_schema.global_status where variable_name='rocksdb_number_sst_entry_singledelete';
START TRANSACTION WITH CONSISTENT ROCKSDB SNAPSHOT;
File Position Gtid_executed
master-bin.000001 734 uuid:1-3
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection con2;
connection con1;
select case when variable_value-@p < 1000 then 'true' else variable_value-@p end from information_schema.global_status where variable_name='rocksdb_number_sst_entry_put';
case when variable_value-@p < 1000 then 'true' else variable_value-@p end
true
@@ -27,10 +30,15 @@ id value
1 10001
2 2
BEGIN;
connection con2;
connection con1;
SELECT COUNT(*) FROM t1;
COUNT(*)
9998
COMMIT;
connection default;
disconnect con1;
disconnect con2;
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize status OK

View File

@@ -105,3 +105,13 @@ SHOW CREATE TABLE t1;
SELECT COUNT(*) FROM t1;
DROP TABLE t1;
# Cleanup temporary #sql files. In the future server will remove these
# automatically but for now we need to do the delete explicit
--disable_query_log
--disable_result_log
let $datadir=`select @@datadir`;
--remove_files_wildcard $datadir/test #sql*
--enable_result_log
--enable_query_log

View File

@@ -82,5 +82,5 @@ autoinc_vars_thread: debug sync point wait timed out
##
information_schema : MariaRocks: requires GTIDs
mysqlbinlog_gtid_skip_empty_trans_rocksdb : MariaRocks: requires GTIDs
read_only_tx : MariaRocks: requires GTIDs
#read_only_tx : MariaRocks: requires GTIDs
rpl_row_triggers : MariaRocks: requires GTIDs

View File

@@ -1 +1 @@
--rocksdb_default_cf_options=write_buffer_size=16k --log-bin --binlog_format=row --gtid_mode=ON --enforce_gtid_consistency --log-slave-updates
--rocksdb_default_cf_options=write_buffer_size=16k --log-bin --binlog_format=row --log-slave-updates

View File

@@ -2,9 +2,9 @@
--source include/have_rocksdb.inc
--source include/count_sessions.inc
--disable_warnings
--source include/have_gtid.inc
#--source include/have_gtid.inc
--enable_warnings
-- let $uuid = `select @@server_uuid;`
#-- let $uuid = `select @@server_uuid;`
--disable_warnings
DROP TABLE IF EXISTS t1;
@@ -20,8 +20,8 @@ INSERT INTO t1 VALUES (1,1);
# Read-only, long-running transaction. SingleDelete/Put shouldn't increase much.
select variable_value into @p from information_schema.global_status where variable_name='rocksdb_number_sst_entry_put';
select variable_value into @s from information_schema.global_status where variable_name='rocksdb_number_sst_entry_singledelete';
-- replace_result $uuid uuid
START TRANSACTION WITH CONSISTENT ROCKSDB SNAPSHOT;
#-- replace_result $uuid uuid
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection con2;
--disable_query_log

View File

@@ -730,6 +730,8 @@ buf_page_is_corrupted(
ulint zip_size,
const fil_space_t* space)
{
DBUG_EXECUTE_IF("buf_page_import_corrupt_failure", return(TRUE); );
ulint checksum_field1;
ulint checksum_field2;
ulint space_id = mach_read_from_4(
@@ -838,8 +840,6 @@ buf_page_is_corrupted(
return(false);
}
DBUG_EXECUTE_IF("buf_page_is_corrupt_failure", return(true); );
ulint page_no = mach_read_from_4(read_buf + FIL_PAGE_OFFSET);
const srv_checksum_algorithm_t curr_algo =
@@ -2956,8 +2956,8 @@ buf_page_get_gen(
ib_mutex_t* fix_mutex = NULL;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad((mtr == NULL) == (mode == BUF_EVICT_IF_IN_POOL));
ut_ad(!mtr || mtr->state == MTR_ACTIVE);
ut_ad((rw_latch == RW_S_LATCH)
|| (rw_latch == RW_X_LATCH)
|| (rw_latch == RW_NO_LATCH));
@@ -2968,23 +2968,29 @@ buf_page_get_gen(
#ifdef UNIV_DEBUG
switch (mode) {
case BUF_EVICT_IF_IN_POOL:
/* After DISCARD TABLESPACE, the tablespace would not exist,
but in IMPORT TABLESPACE, PageConverter::operator() must
replace any old pages, which were not evicted during DISCARD.
Skip the assertion on zip_size. */
break;
case BUF_GET_NO_LATCH:
ut_ad(rw_latch == RW_NO_LATCH);
break;
/* fall through */
case BUF_GET:
case BUF_GET_IF_IN_POOL:
case BUF_PEEK_IF_IN_POOL:
case BUF_GET_IF_IN_POOL_OR_WATCH:
case BUF_GET_POSSIBLY_FREED:
ut_ad(zip_size == fil_space_get_zip_size(space));
break;
default:
ut_error;
}
#endif /* UNIV_DEBUG */
ut_ad(zip_size == fil_space_get_zip_size(space));
ut_ad(ut_is_2pow(zip_size));
#ifndef UNIV_LOG_DEBUG
ut_ad(!ibuf_inside(mtr)
ut_ad(!mtr || !ibuf_inside(mtr)
|| ibuf_page_low(space, zip_size, offset,
FALSE, file, line, NULL));
#endif
@@ -3054,9 +3060,11 @@ loop:
rw_lock_x_unlock(hash_lock);
}
if (mode == BUF_GET_IF_IN_POOL
|| mode == BUF_PEEK_IF_IN_POOL
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
switch (mode) {
case BUF_GET_IF_IN_POOL:
case BUF_GET_IF_IN_POOL_OR_WATCH:
case BUF_PEEK_IF_IN_POOL:
case BUF_EVICT_IF_IN_POOL:
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX));
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_SHARED));
@@ -3145,8 +3153,10 @@ got_block:
ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
if (mode == BUF_GET_IF_IN_POOL || mode == BUF_PEEK_IF_IN_POOL) {
switch (mode) {
case BUF_GET_IF_IN_POOL:
case BUF_PEEK_IF_IN_POOL:
case BUF_EVICT_IF_IN_POOL:
bool must_read;
{
@@ -3184,6 +3194,22 @@ got_block:
case BUF_BLOCK_FILE_PAGE:
ut_ad(fix_mutex != &buf_pool->zip_mutex);
if (UNIV_UNLIKELY(mode == BUF_EVICT_IF_IN_POOL)) {
evict_from_pool:
ut_ad(!fix_block->page.oldest_modification);
mutex_enter(&buf_pool->LRU_list_mutex);
buf_block_unfix(fix_block);
mutex_enter(fix_mutex);
if (!buf_LRU_free_page(&fix_block->page, true)) {
ut_ad(0);
mutex_exit(&buf_pool->LRU_list_mutex);
}
mutex_exit(fix_mutex);
return(NULL);
}
break;
case BUF_BLOCK_ZIP_PAGE:
@@ -3218,6 +3244,10 @@ got_block:
goto loop;
}
if (UNIV_UNLIKELY(mode == BUF_EVICT_IF_IN_POOL)) {
goto evict_from_pool;
}
/* Buffer-fix the block so that it cannot be evicted
or relocated while we are attempting to allocate an
uncompressed page. */
@@ -4798,7 +4828,7 @@ database_corrupted:
if (err != DB_SUCCESS) {
/* Not a real corruption if it was triggered by
error injection */
DBUG_EXECUTE_IF("buf_page_is_corrupt_failure",
DBUG_EXECUTE_IF("buf_page_import_corrupt_failure",
if (bpage->space > TRX_SYS_SPACE) {
buf_mark_space_corrupt(bpage);
ib_logf(IB_LOG_LEVEL_INFO,
@@ -4866,7 +4896,7 @@ database_corrupted:
}
}
DBUG_EXECUTE_IF("buf_page_is_corrupt_failure",
DBUG_EXECUTE_IF("buf_page_import_corrupt_failure",
page_not_corrupt: bpage = bpage; );
if (recv_recovery_is_on()) {

View File

@@ -571,26 +571,20 @@ buf_flush_or_remove_page(
return(processed);
}
/******************************************************************//**
Remove all dirty pages belonging to a given tablespace inside a specific
/** Remove all dirty pages belonging to a given tablespace inside a specific
buffer pool instance when we are deleting the data file(s) of that
tablespace. The pages still remain a part of LRU and are evicted from
the list as they age towards the tail of the LRU.
@param[in,out] buf_pool buffer pool
@param[in] id tablespace identifier
@param[in] trx transaction (to check for interrupt),
or NULL if the files should not be written to
@retval DB_SUCCESS if all freed
@retval DB_FAIL if not all freed
@retval DB_INTERRUPTED if the transaction was interrupted */
static MY_ATTRIBUTE((nonnull(1), warn_unused_result))
dberr_t
buf_flush_or_remove_pages(
/*======================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint id, /*!< in: target space id for which
to remove or flush pages */
bool flush, /*!< in: flush to disk if true but
don't remove else remove without
flushing to disk */
const trx_t* trx) /*!< to check if the operation must
be interrupted, can be 0 */
buf_flush_or_remove_pages(buf_pool_t* buf_pool, ulint id, const trx_t* trx)
{
buf_page_t* prev;
buf_page_t* bpage;
@@ -621,7 +615,7 @@ rescan:
/* Skip this block, as it does not belong to
the target space. */
} else if (!buf_flush_or_remove_page(buf_pool, bpage, flush,
} else if (!buf_flush_or_remove_page(buf_pool, bpage, trx,
&must_restart)) {
/* Remove was unsuccessful, we have to try again
@@ -647,7 +641,7 @@ rescan:
/* Cannot trust the prev pointer */
break;
}
} else if (flush) {
} else if (trx) {
/* The processing was successful. And during the
processing we have released all the buf_pool mutexes
@@ -674,19 +668,17 @@ rescan:
break;
}
#ifdef DBUG_OFF
if (flush) {
if (trx) {
DBUG_EXECUTE_IF("ib_export_flush_crash",
static ulint n_pages;
if (++n_pages == 4) {DBUG_SUICIDE();});
}
#endif /* DBUG_OFF */
/* The check for trx is interrupted is expensive, we want
to check every N iterations. */
if (!processed && trx && trx_is_interrupted(trx)) {
buf_flush_list_mutex_exit(buf_pool);
return(DB_INTERRUPTED);
/* The check for trx is interrupted is
expensive, we want to check every N iterations. */
if (!processed && trx_is_interrupted(trx)) {
buf_flush_list_mutex_exit(buf_pool);
return(DB_INTERRUPTED);
}
}
}
@@ -695,28 +687,25 @@ rescan:
return(all_freed ? DB_SUCCESS : DB_FAIL);
}
/******************************************************************//**
Remove or flush all the dirty pages that belong to a given tablespace
/** Remove or flush all the dirty pages that belong to a given tablespace
inside a specific buffer pool instance. The pages will remain in the LRU
list and will be evicted from the LRU list as they age and move towards
the tail of the LRU list. */
the tail of the LRU list.
@param[in,out] buf_pool buffer pool
@param[in] id tablespace identifier
@param[in] trx transaction (to check for interrupt),
or NULL if the files should not be written to
*/
static MY_ATTRIBUTE((nonnull(1)))
void
buf_flush_dirty_pages(
/*==================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint id, /*!< in: space id */
bool flush, /*!< in: flush to disk if true otherwise
remove the pages without flushing */
const trx_t* trx) /*!< to check if the operation must
be interrupted */
buf_flush_dirty_pages(buf_pool_t* buf_pool, ulint id, const trx_t* trx)
{
dberr_t err;
do {
mutex_enter(&buf_pool->LRU_list_mutex);
err = buf_flush_or_remove_pages(buf_pool, id, flush, trx);
err = buf_flush_or_remove_pages(buf_pool, id, trx);
mutex_exit(&buf_pool->LRU_list_mutex);
@@ -737,239 +726,27 @@ buf_flush_dirty_pages(
|| buf_pool_get_dirty_pages_count(buf_pool, id) == 0);
}
/******************************************************************//**
Remove all pages that belong to a given tablespace inside a specific
buffer pool instance when we are DISCARDing the tablespace. */
static MY_ATTRIBUTE((nonnull))
/** Empty the flush list for all pages belonging to a tablespace.
@param[in] id tablespace identifier
@param[in] trx transaction, for checking for user interrupt;
or NULL if nothing is to be written
@param[in] drop_ahi whether to drop the adaptive hash index */
UNIV_INTERN
void
buf_LRU_remove_all_pages(
/*=====================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint id) /*!< in: space id */
buf_LRU_flush_or_remove_pages(ulint id, const trx_t* trx, bool drop_ahi)
{
buf_page_t* bpage;
ibool all_freed;
scan_again:
mutex_enter(&buf_pool->LRU_list_mutex);
all_freed = TRUE;
for (bpage = UT_LIST_GET_LAST(buf_pool->LRU);
bpage != NULL;
/* No op */) {
prio_rw_lock_t* hash_lock;
buf_page_t* prev_bpage;
ib_mutex_t* block_mutex = NULL;
ut_a(buf_page_in_file(bpage));
ut_ad(bpage->in_LRU_list);
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
/* It is safe to check bpage->space and bpage->io_fix while
holding buf_pool->LRU_list_mutex only and later recheck
while holding the buf_page_get_mutex() mutex. */
if (buf_page_get_space(bpage) != id) {
/* Skip this block, as it does not belong to
the space that is being invalidated. */
goto next_page;
} else if (UNIV_UNLIKELY(buf_page_get_io_fix_unlocked(bpage)
!= BUF_IO_NONE)) {
/* We cannot remove this page during this scan
yet; maybe the system is currently reading it
in, or flushing the modifications to the file */
all_freed = FALSE;
goto next_page;
} else {
ulint fold = buf_page_address_fold(
bpage->space, bpage->offset);
hash_lock = buf_page_hash_lock_get(buf_pool, fold);
rw_lock_x_lock(hash_lock);
block_mutex = buf_page_get_mutex(bpage);
mutex_enter(block_mutex);
if (UNIV_UNLIKELY(
buf_page_get_space(bpage) != id
|| bpage->buf_fix_count > 0
|| (buf_page_get_io_fix(bpage)
!= BUF_IO_NONE))) {
mutex_exit(block_mutex);
rw_lock_x_unlock(hash_lock);
/* We cannot remove this page during
this scan yet; maybe the system is
currently reading it in, or flushing
the modifications to the file */
all_freed = FALSE;
goto next_page;
}
for (ulint i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool = buf_pool_from_array(i);
if (drop_ahi) {
buf_LRU_drop_page_hash_for_tablespace(buf_pool, id);
}
ut_ad(mutex_own(block_mutex));
#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
"Dropping space %lu page %lu\n",
(ulong) buf_page_get_space(bpage),
(ulong) buf_page_get_page_no(bpage));
}
#endif
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
/* Do nothing, because the adaptive hash index
covers uncompressed pages only. */
} else if (((buf_block_t*) bpage)->index) {
ulint page_no;
ulint zip_size;
mutex_exit(&buf_pool->LRU_list_mutex);
zip_size = buf_page_get_zip_size(bpage);
page_no = buf_page_get_page_no(bpage);
mutex_exit(block_mutex);
rw_lock_x_unlock(hash_lock);
/* Note that the following call will acquire
and release block->lock X-latch. */
btr_search_drop_page_hash_when_freed(
id, zip_size, page_no);
goto scan_again;
}
if (bpage->oldest_modification != 0) {
buf_flush_remove(bpage);
}
ut_ad(!bpage->in_flush_list);
/* Remove from the LRU list. */
if (buf_LRU_block_remove_hashed(bpage, true)) {
mutex_enter(block_mutex);
buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
mutex_exit(block_mutex);
} else {
ut_ad(block_mutex == &buf_pool->zip_mutex);
}
ut_ad(!mutex_own(block_mutex));
#ifdef UNIV_SYNC_DEBUG
/* buf_LRU_block_remove_hashed() releases the hash_lock */
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_EX));
ut_ad(!rw_lock_own(hash_lock, RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
next_page:
bpage = prev_bpage;
buf_flush_dirty_pages(buf_pool, id, trx);
}
mutex_exit(&buf_pool->LRU_list_mutex);
if (!all_freed) {
os_thread_sleep(20000);
goto scan_again;
}
}
/******************************************************************//**
Remove pages belonging to a given tablespace inside a specific
buffer pool instance when we are deleting the data file(s) of that
tablespace. The pages still remain a part of LRU and are evicted from
the list as they age towards the tail of the LRU only if buf_remove
is BUF_REMOVE_FLUSH_NO_WRITE. */
static MY_ATTRIBUTE((nonnull(1)))
void
buf_LRU_remove_pages(
/*=================*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint id, /*!< in: space id */
buf_remove_t buf_remove, /*!< in: remove or flush strategy */
const trx_t* trx) /*!< to check if the operation must
be interrupted */
{
switch (buf_remove) {
case BUF_REMOVE_ALL_NO_WRITE:
buf_LRU_remove_all_pages(buf_pool, id);
break;
case BUF_REMOVE_FLUSH_NO_WRITE:
ut_a(trx == 0);
buf_flush_dirty_pages(buf_pool, id, false, NULL);
break;
case BUF_REMOVE_FLUSH_WRITE:
ut_a(trx != 0);
buf_flush_dirty_pages(buf_pool, id, true, trx);
if (trx && !trx_is_interrupted(trx)) {
/* Ensure that all asynchronous IO is completed. */
os_aio_wait_until_no_pending_writes();
fil_flush(id);
break;
}
}
/******************************************************************//**
Flushes all dirty pages or removes all pages belonging
to a given tablespace. A PROBLEM: if readahead is being started, what
guarantees that it will not try to read in pages after this operation
has completed? */
UNIV_INTERN
void
buf_LRU_flush_or_remove_pages(
/*==========================*/
ulint id, /*!< in: space id */
buf_remove_t buf_remove, /*!< in: remove or flush strategy */
const trx_t* trx) /*!< to check if the operation must
be interrupted */
{
ulint i;
/* Before we attempt to drop pages one by one we first
attempt to drop page hash index entries in batches to make
it more efficient. The batching attempt is a best effort
attempt and does not guarantee that all pages hash entries
will be dropped. We get rid of remaining page hash entries
one by one below. */
for (i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t* buf_pool;
buf_pool = buf_pool_from_array(i);
switch (buf_remove) {
case BUF_REMOVE_ALL_NO_WRITE:
buf_LRU_drop_page_hash_for_tablespace(buf_pool, id);
break;
case BUF_REMOVE_FLUSH_NO_WRITE:
/* It is a DROP TABLE for a single table
tablespace. No AHI entries exist because
we already dealt with them when freeing up
extents. */
case BUF_REMOVE_FLUSH_WRITE:
/* We allow read-only queries against the
table, there is no need to drop the AHI entries. */
break;
}
buf_LRU_remove_pages(buf_pool, id, buf_remove, trx);
}
}

View File

@@ -1679,7 +1679,7 @@ dict_table_rename_in_cache(
filepath = fil_make_ibd_name(table->name, false);
}
fil_delete_tablespace(table->space, BUF_REMOVE_ALL_NO_WRITE);
fil_delete_tablespace(table->space, true);
/* Delete any temp file hanging around. */
if (os_file_status(filepath, &exists, &ftype)

View File

@@ -2572,8 +2572,7 @@ fil_op_log_parse_or_replay(
switch (type) {
case MLOG_FILE_DELETE:
if (fil_tablespace_exists_in_mem(space_id)) {
dberr_t err = fil_delete_tablespace(
space_id, BUF_REMOVE_FLUSH_NO_WRITE);
dberr_t err = fil_delete_tablespace(space_id);
ut_a(err == DB_SUCCESS);
}
@@ -2851,7 +2850,7 @@ fil_close_tablespace(
completely and permanently. The flag stop_new_ops also prevents
fil_flush() from being applied to this tablespace. */
buf_LRU_flush_or_remove_pages(id, BUF_REMOVE_FLUSH_WRITE, trx);
buf_LRU_flush_or_remove_pages(id, trx);
#endif
mutex_enter(&fil_system->mutex);
@@ -2878,18 +2877,13 @@ fil_close_tablespace(
return(err);
}
/*******************************************************************//**
Deletes a single-table tablespace. The tablespace must be cached in the
memory cache.
/** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier
@param[in] drop_ahi whether to drop the adaptive hash index
@return DB_SUCCESS or error */
UNIV_INTERN
dberr_t
fil_delete_tablespace(
/*==================*/
ulint id, /*!< in: space id */
buf_remove_t buf_remove) /*!< in: specify the action to take
on the tables pages in the buffer
pool */
fil_delete_tablespace(ulint id, bool drop_ahi)
{
char* path = 0;
fil_space_t* space = 0;
@@ -2945,7 +2939,7 @@ fil_delete_tablespace(
To deal with potential read requests by checking the
::stop_new_ops flag in fil_io() */
buf_LRU_flush_or_remove_pages(id, buf_remove, 0);
buf_LRU_flush_or_remove_pages(id, NULL, drop_ahi);
#endif /* !UNIV_HOTBACKUP */
@@ -3056,7 +3050,7 @@ fil_discard_tablespace(
{
dberr_t err;
switch (err = fil_delete_tablespace(id, BUF_REMOVE_ALL_NO_WRITE)) {
switch (err = fil_delete_tablespace(id, true)) {
case DB_SUCCESS:
break;
@@ -4863,7 +4857,7 @@ fil_load_single_table_tablespace(
/* Check for a link file which locates a remote tablespace. */
remote.success = fil_open_linked_file(
remote.success = (IS_XTRABACKUP() && !srv_backup_mode) ? 0 : fil_open_linked_file(
tablename, &remote.filepath, &remote.file, FALSE);
/* Read the first page of the remote tablespace */

View File

@@ -10947,7 +10947,7 @@ wsrep_append_foreign_key(
shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE,
copy);
if (rcode) {
DBUG_PRINT("wsrep", ("row key failed: %lu", rcode));
DBUG_PRINT("wsrep", ("row key failed: %zu", rcode));
WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu",
(wsrep_thd_query(thd)) ?
wsrep_thd_query(thd) : "void", rcode);
@@ -19714,7 +19714,7 @@ wsrep_innobase_kill_one_trx(
wsrep_thd_awake(thd, signal);
} else {
/* abort currently executing query */
DBUG_PRINT("wsrep",("sending KILL_QUERY to: %ld",
DBUG_PRINT("wsrep",("sending KILL_QUERY to: %lu",
thd_get_thread_id(thd)));
WSREP_DEBUG("kill query for: %ld",
thd_get_thread_id(thd));
@@ -19841,7 +19841,8 @@ wsrep_fake_trx_id(
mutex_enter(&trx_sys->mutex);
trx_id_t trx_id = trx_sys_get_new_trx_id();
mutex_exit(&trx_sys->mutex);
WSREP_DEBUG("innodb fake trx id: %lu thd: %s", trx_id, wsrep_thd_query(thd));
WSREP_DEBUG("innodb fake trx id: " TRX_ID_FMT " thd: %s",
trx_id, wsrep_thd_query(thd));
wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id);
}

View File

@@ -5178,7 +5178,20 @@ ibuf_check_bitmap_on_import(
return(DB_TABLE_NOT_FOUND);
}
size = fil_space_get_size(space_id);
mtr_t mtr;
mtr_start(&mtr);
{
buf_block_t* sp = buf_page_get(space_id, zip_size, 0,
RW_S_LATCH, &mtr);
if (sp) {
size = mach_read_from_4(
FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ sp->frame);
} else {
size = 0;
}
}
mtr_commit(&mtr);
if (size == 0) {
return(DB_TABLE_NOT_FOUND);
@@ -5189,7 +5202,6 @@ ibuf_check_bitmap_on_import(
page_size = zip_size ? zip_size : UNIV_PAGE_SIZE;
for (page_no = 0; page_no < size; page_no += page_size) {
mtr_t mtr;
page_t* bitmap_page;
ulint i;

View File

@@ -58,6 +58,7 @@ Created 11/5/1995 Heikki Tuuri
#define BUF_GET_POSSIBLY_FREED 16
/*!< Like BUF_GET, but do not mind
if the file page has been freed. */
#define BUF_EVICT_IF_IN_POOL 20 /*!< evict a clean block if found */
/* @} */
/** @name Modes for buf_page_get_known_nowait */
/* @{ */

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -53,19 +54,14 @@ These are low-level functions
/** Minimum LRU list length for which the LRU_old pointer is defined */
#define BUF_LRU_OLD_MIN_LEN 512 /* 8 megabytes of 16k pages */
/******************************************************************//**
Flushes all dirty pages or removes all pages belonging
to a given tablespace. A PROBLEM: if readahead is being started, what
guarantees that it will not try to read in pages after this operation
has completed? */
/** Empty the flush list for all pages belonging to a tablespace.
@param[in] id tablespace identifier
@param[in] trx transaction, for checking for user interrupt;
or NULL if nothing is to be written
@param[in] drop_ahi whether to drop the adaptive hash index */
UNIV_INTERN
void
buf_LRU_flush_or_remove_pages(
/*==========================*/
ulint id, /*!< in: space id */
buf_remove_t buf_remove, /*!< in: remove or flush strategy */
const trx_t* trx); /*!< to check if the operation must
be interrupted */
buf_LRU_flush_or_remove_pages(ulint id, const trx_t* trx, bool drop_ahi=false);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
/********************************************************************//**

View File

@@ -58,17 +58,6 @@ enum buf_flush_t {
BUF_FLUSH_N_TYPES /*!< index of last element + 1 */
};
/** Algorithm to remove the pages for a tablespace from the buffer pool.
See buf_LRU_flush_or_remove_pages(). */
enum buf_remove_t {
BUF_REMOVE_ALL_NO_WRITE, /*!< Remove all pages from the buffer
pool, don't write or sync to disk */
BUF_REMOVE_FLUSH_NO_WRITE, /*!< Remove only, from the flush list,
don't write or sync to disk */
BUF_REMOVE_FLUSH_WRITE /*!< Flush dirty pages to disk only
don't remove from the buffer pool */
};
/** Flags for io_fix types */
enum buf_io_fix {
BUF_IO_NONE = 0, /**< no pending I/O */

View File

@@ -849,18 +849,13 @@ fil_op_log_parse_or_replay(
only be parsed but not replayed */
ulint log_flags); /*!< in: redo log flags
(stored in the page number parameter) */
/*******************************************************************//**
Deletes a single-table tablespace. The tablespace must be cached in the
memory cache.
@return TRUE if success */
/** Delete a tablespace and associated .ibd file.
@param[in] id tablespace identifier
@param[in] drop_ahi whether to drop the adaptive hash index
@return DB_SUCCESS or error */
UNIV_INTERN
dberr_t
fil_delete_tablespace(
/*==================*/
ulint id, /*!< in: space id */
buf_remove_t buf_remove); /*!< in: specify the action to take
on the tables pages in the buffer
pool */
fil_delete_tablespace(ulint id, bool drop_ahi = false);
/*******************************************************************//**
Closes a single-table tablespace. The tablespace must be cached in the
memory cache. Free all pages used by the tablespace.

View File

@@ -2141,6 +2141,7 @@ lock_rec_insert_by_trx_age(
return DB_SUCCESS;
}
#ifdef UNIV_DEBUG
static
bool
lock_queue_validate(
@@ -2174,6 +2175,7 @@ lock_queue_validate(
}
return true;
}
#endif /* UNIV_DEBUG */
static
void

View File

@@ -2570,8 +2570,8 @@ os_file_get_size(
return(offset);
#else
return((os_offset_t) lseek(file, 0, SEEK_END));
struct stat statbuf;
return fstat(file, &statbuf) ? os_offset_t(-1) : statbuf.st_size;
#endif /* __WIN__ */
}
@@ -2625,19 +2625,29 @@ os_file_set_size(
if (srv_use_posix_fallocate) {
int err;
do {
err = posix_fallocate(file, 0, size);
os_offset_t current_size = os_file_get_size(file);
err = current_size >= size
? 0 : posix_fallocate(file, current_size,
size - current_size);
} while (err == EINTR
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
if (err) {
switch (err) {
case 0:
return true;
default:
ib_logf(IB_LOG_LEVEL_ERROR,
"preallocating " INT64PF " bytes for"
"file %s failed with error %d",
size, name, err);
/* fall through */
case EINTR:
errno = err;
return false;
case EINVAL:
/* fall back to the code below */
break;
}
/* Set errno because posix_fallocate() does not do it.*/
errno = err;
return(!err);
}
# endif
@@ -2679,11 +2689,12 @@ os_file_set_size(
}
current_size += n_bytes;
} while (current_size < size);
} while (current_size < size
&& srv_shutdown_state == SRV_SHUTDOWN_NONE);
free(buf2);
return(ret && os_file_flush(file));
return(ret && current_size >= size && os_file_flush(file));
#endif
}

View File

@@ -1602,18 +1602,16 @@ PageConverter::PageConverter(
:
AbstractCallback(trx),
m_cfg(cfg),
m_index(cfg->m_indexes),
m_current_lsn(log_get_lsn()),
m_page_zip_ptr(0),
m_heap(0) UNIV_NOTHROW
m_rec_iter(),
m_offsets_(), m_offsets(m_offsets_),
m_heap(0),
m_cluster_index(dict_table_get_first_index(cfg->m_table)) UNIV_NOTHROW
{
m_index = m_cfg->m_indexes;
m_current_lsn = log_get_lsn();
ut_a(m_current_lsn > 0);
m_offsets = m_offsets_;
rec_offs_init(m_offsets_);
m_cluster_index = dict_table_get_first_index(m_cfg->m_table);
}
/**
@@ -2104,7 +2102,7 @@ PageConverter::operator() (
we can work on them */
if ((err = update_page(block, page_type)) != DB_SUCCESS) {
return(err);
break;
}
/* Note: For compressed pages this function will write to the
@@ -2141,9 +2139,15 @@ PageConverter::operator() (
"%s: Page %lu at offset " UINT64PF " looks corrupted.",
m_filepath, (ulong) (offset / m_page_size), offset);
return(DB_CORRUPTION);
err = DB_CORRUPTION;
}
/* If we already had and old page with matching number
in the buffer pool, evict it now, because
we no longer evict the pages on DISCARD TABLESPACE. */
buf_page_get_gen(get_space_id(), get_zip_size(), block->page.offset,
RW_NO_LATCH, NULL, BUF_EVICT_IF_IN_POOL,
__FILE__, __LINE__, NULL);
return(err);
}
@@ -3717,8 +3721,7 @@ row_import_for_mysql(
The only dirty pages generated should be from the pessimistic purge
of delete marked records that couldn't be purged in Phase I. */
buf_LRU_flush_or_remove_pages(
prebuilt->table->space, BUF_REMOVE_FLUSH_WRITE, trx);
buf_LRU_flush_or_remove_pages(prebuilt->table->space, trx);
if (trx_is_interrupted(trx)) {
ib_logf(IB_LOG_LEVEL_INFO, "Phase III - Flush interrupted");

View File

@@ -2494,10 +2494,7 @@ err_exit:
/* We already have .ibd file here. it should be deleted. */
if (table->space
&& fil_delete_tablespace(
table->space,
BUF_REMOVE_FLUSH_NO_WRITE)
!= DB_SUCCESS) {
&& fil_delete_tablespace(table->space) != DB_SUCCESS) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -3132,9 +3129,6 @@ row_discard_tablespace(
4) FOREIGN KEY operations: if table->n_foreign_key_checks_running > 0,
we do not allow the discard. */
/* Play safe and remove all insert buffer entries, though we should
have removed them already when DISCARD TABLESPACE was called */
ibuf_delete_for_discarded_space(table->space);
table_id_t new_id;
@@ -4516,9 +4510,7 @@ row_drop_table_for_mysql(
fil_delete_file(filepath);
} else if (fil_delete_tablespace(
space_id,
BUF_REMOVE_FLUSH_NO_WRITE)
} else if (fil_delete_tablespace(space_id)
!= DB_SUCCESS) {
fprintf(stderr,
"InnoDB: We removed now the InnoDB"

View File

@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -542,8 +543,7 @@ row_quiesce_table_start(
}
if (!trx_is_interrupted(trx)) {
buf_LRU_flush_or_remove_pages(
table->space, BUF_REMOVE_FLUSH_WRITE, trx);
buf_LRU_flush_or_remove_pages(table->space, trx);
if (trx_is_interrupted(trx)) {

View File

@@ -2025,6 +2025,7 @@ trx_undo_free_prepared(
/* lock_trx_release_locks() assigns
trx->is_recovered=false */
ut_a(srv_read_only_mode
|| srv_apply_log_only
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
break;
default: