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:
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 (
|
||||
|
||||
2
mysql-test/r/delimiter_command_case_sensitivity.result
Normal file
2
mysql-test/r/delimiter_command_case_sensitivity.result
Normal file
@@ -0,0 +1,2 @@
|
||||
1
|
||||
1
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
#
|
||||
#
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
#
|
||||
#
|
||||
|
||||
@@ -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
|
||||
#
|
||||
#
|
||||
|
||||
13
mysql-test/suite/mariabackup/data_directory.result
Normal file
13
mysql-test/suite/mariabackup/data_directory.result
Normal 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;
|
||||
23
mysql-test/suite/mariabackup/data_directory.test
Normal file
23
mysql-test/suite/mariabackup/data_directory.test
Normal 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;
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
1
mysql-test/suite/mariabackup/partition_datadir.opt
Normal file
1
mysql-test/suite/mariabackup/partition_datadir.opt
Normal file
@@ -0,0 +1 @@
|
||||
--partition
|
||||
22
mysql-test/suite/mariabackup/partition_datadir.result
Normal file
22
mysql-test/suite/mariabackup/partition_datadir.result
Normal 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;
|
||||
24
mysql-test/suite/mariabackup/partition_datadir.test
Normal file
24
mysql-test/suite/mariabackup/partition_datadir.test
Normal 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;
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 '';
|
||||
|
||||
@@ -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 '';
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
--innodb-buffer-pool-load-at-startup=off
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
3
mysql-test/t/delimiter_case_mdev_10728.sql
Normal file
3
mysql-test/t/delimiter_case_mdev_10728.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
DeLiMiTeR A;
|
||||
SELECT 1 A;
|
||||
delimiter ;
|
||||
4
mysql-test/t/delimiter_command_case_sensitivity.test
Normal file
4
mysql-test/t/delimiter_command_case_sensitivity.test
Normal file
@@ -0,0 +1,4 @@
|
||||
source include/not_embedded.inc;
|
||||
|
||||
# MDEV-10728
|
||||
--exec $MYSQL --default-character-set=binary < "t/delimiter_case_mdev_10728.sql"
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 #
|
||||
|
||||
@@ -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
|
||||
|
||||
#
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 #
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
--source include/have_partition.inc
|
||||
# Save the initial number of concurrent sessions.
|
||||
--source include/count_sessions.inc
|
||||
|
||||
|
||||
@@ -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++)= ' ';
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
25
sql/item.cc
25
sql/item.cc
@@ -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;
|
||||
}
|
||||
|
||||
25
sql/item.h
25
sql/item.h
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -375,7 +375,7 @@ public:
|
||||
virtual void get_cache_parameters(List<Item> ¶meters);
|
||||
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; }
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
/* @{ */
|
||||
|
||||
@@ -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
|
||||
/********************************************************************//**
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
/* @{ */
|
||||
|
||||
@@ -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
|
||||
/********************************************************************//**
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user