Merge 10.11 into 11.0
This commit is contained in:
commit
0fb897b081
@ -20,8 +20,6 @@ a RIGHT(b,20)
|
|||||||
2 bbbbbbbbbbbbbbbbbbbb
|
2 bbbbbbbbbbbbbbbbbbbb
|
||||||
connection default;
|
connection default;
|
||||||
SET DEBUG='+d,row_ins_extern_checkpoint';
|
SET DEBUG='+d,row_ins_extern_checkpoint';
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
SET DEBUG_SYNC='before_row_ins_extern_latch SIGNAL rec_not_blob WAIT_FOR crash';
|
SET DEBUG_SYNC='before_row_ins_extern_latch SIGNAL rec_not_blob WAIT_FOR crash';
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
@ -88,8 +86,6 @@ BEGIN;
|
|||||||
INSERT INTO t2 VALUES (347);
|
INSERT INTO t2 VALUES (347);
|
||||||
connection default;
|
connection default;
|
||||||
SET DEBUG='+d,row_upd_extern_checkpoint';
|
SET DEBUG='+d,row_upd_extern_checkpoint';
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
|
SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
|
||||||
UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2;
|
UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2;
|
||||||
connection con2;
|
connection con2;
|
||||||
@ -126,8 +122,6 @@ BEGIN;
|
|||||||
INSERT INTO t2 VALUES (33101);
|
INSERT INTO t2 VALUES (33101);
|
||||||
connection default;
|
connection default;
|
||||||
SET DEBUG='+d,row_upd_extern_checkpoint';
|
SET DEBUG='+d,row_upd_extern_checkpoint';
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
SET DEBUG_SYNC='after_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
|
SET DEBUG_SYNC='after_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
|
||||||
UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2;
|
UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2;
|
||||||
connection con2;
|
connection con2;
|
||||||
|
@ -92,8 +92,6 @@ ALTER TABLE t1 FORCE, ADD COLUMN k4 int;
|
|||||||
connection default;
|
connection default;
|
||||||
SET DEBUG_SYNC= 'now WAIT_FOR opened';
|
SET DEBUG_SYNC= 'now WAIT_FOR opened';
|
||||||
SET debug = '+d,row_log_tmpfile_fail';
|
SET debug = '+d,row_log_tmpfile_fail';
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
INSERT INTO t1 select NULL,'aaa','bbb' from t480;
|
INSERT INTO t1 select NULL,'aaa','bbb' from t480;
|
||||||
INSERT INTO t1 select NULL,'aaaa','bbbb' from t480;
|
INSERT INTO t1 select NULL,'aaaa','bbbb' from t480;
|
||||||
SET DEBUG_SYNC= 'now SIGNAL flushed';
|
SET DEBUG_SYNC= 'now SIGNAL flushed';
|
||||||
|
@ -36,16 +36,10 @@ SET DEBUG_DBUG = '+d,innodb_OOM_prepare_inplace_alter';
|
|||||||
ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE;
|
ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE;
|
||||||
ERROR HY000: Out of memory.
|
ERROR HY000: Out of memory.
|
||||||
SET SESSION DEBUG = @saved_debug_dbug;
|
SET SESSION DEBUG = @saved_debug_dbug;
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
SET SESSION DEBUG = '+d,innodb_OOM_inplace_alter';
|
SET SESSION DEBUG = '+d,innodb_OOM_inplace_alter';
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE;
|
ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE;
|
||||||
ERROR HY000: Out of memory.
|
ERROR HY000: Out of memory.
|
||||||
SET SESSION DEBUG = @saved_debug_dbug;
|
SET SESSION DEBUG = @saved_debug_dbug;
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE;
|
ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ALGORITHM=INPLACE, LOCK=NONE;
|
||||||
connection default;
|
connection default;
|
||||||
SHOW CREATE TABLE t1;
|
SHOW CREATE TABLE t1;
|
||||||
|
@ -16,8 +16,6 @@ SET @save_dbug = @@debug_dbug;
|
|||||||
SET DEBUG_DBUG = '+d,do_page_reorganize,do_lock_reverse_page_reorganize';
|
SET DEBUG_DBUG = '+d,do_page_reorganize,do_lock_reverse_page_reorganize';
|
||||||
insert into t1(f2) values (repeat('+', 100));
|
insert into t1(f2) values (repeat('+', 100));
|
||||||
SET DEBUG = @save_dbug;
|
SET DEBUG = @save_dbug;
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
commit;
|
commit;
|
||||||
connection con1;
|
connection con1;
|
||||||
f1
|
f1
|
||||||
|
@ -20,8 +20,6 @@ END//
|
|||||||
CALL populate_t1;
|
CALL populate_t1;
|
||||||
SET autocommit=1;
|
SET autocommit=1;
|
||||||
SET SESSION debug="+d,fts_instrument_result_cache_limit";
|
SET SESSION debug="+d,fts_instrument_result_cache_limit";
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
ALTER TABLE t1 ADD FULLTEXT INDEX `text_content_idx` (`text_content`);
|
ALTER TABLE t1 ADD FULLTEXT INDEX `text_content_idx` (`text_content`);
|
||||||
SELECT FTS_DOC_ID, text_content
|
SELECT FTS_DOC_ID, text_content
|
||||||
FROM t1
|
FROM t1
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
create table t1 (i int, g geometry not null, spatial index (g))engine=innodb;
|
create table t1 (i int, g geometry not null, spatial index (g))engine=innodb;
|
||||||
SET SESSION debug="+d,rtree_test_check_count";
|
SET SESSION debug="+d,rtree_test_check_count";
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
insert into t1 values (1, POINT(1,1));
|
insert into t1 values (1, POINT(1,1));
|
||||||
insert into t1 values (1, POINT(1.5,1.5));
|
insert into t1 values (1, POINT(1.5,1.5));
|
||||||
insert into t1 values (1, POINT(3,3));
|
insert into t1 values (1, POINT(3,3));
|
||||||
|
@ -408,8 +408,6 @@ update t1 set a=point(5,5), b=point(5,5), c=5 where i < 3;
|
|||||||
ERROR 23000: Duplicate entry '5' for key 'c'
|
ERROR 23000: Duplicate entry '5' for key 'c'
|
||||||
rollback;
|
rollback;
|
||||||
set session debug="+d,row_mysql_crash_if_error";
|
set session debug="+d,row_mysql_crash_if_error";
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
update t1 set a=point(5,5), b=point(5,5), c=5 where i < 3;
|
update t1 set a=point(5,5), b=point(5,5), c=5 where i < 3;
|
||||||
ERROR HY000: Lost connection to server during query
|
ERROR HY000: Lost connection to server during query
|
||||||
insert into t1 values(5, point(5,5), point(5,5), 5);
|
insert into t1 values(5, point(5,5), point(5,5), 5);
|
||||||
|
@ -44,8 +44,6 @@ count(*)
|
|||||||
0
|
0
|
||||||
SET @saved_dbug = @@SESSION.debug_dbug;
|
SET @saved_dbug = @@SESSION.debug_dbug;
|
||||||
SET DEBUG='+d,page_copy_rec_list_start_compress_fail';
|
SET DEBUG='+d,page_copy_rec_list_start_compress_fail';
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
delete from t1;
|
delete from t1;
|
||||||
select count(*) from t1 where MBRWithin(t1.c2, @g1);
|
select count(*) from t1 where MBRWithin(t1.c2, @g1);
|
||||||
count(*)
|
count(*)
|
||||||
|
@ -31,7 +31,5 @@ COUNT(*)
|
|||||||
0
|
0
|
||||||
ALTER TABLE t1 DROP INDEX idx, ADD SPATIAL INDEX idx3(c2);
|
ALTER TABLE t1 DROP INDEX idx, ADD SPATIAL INDEX idx3(c2);
|
||||||
SET SESSION debug="+d,row_merge_instrument_log_check_flush";
|
SET SESSION debug="+d,row_merge_instrument_log_check_flush";
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
ALTER TABLE t1 DROP INDEX idx3, ADD SPATIAL INDEX idx4(c2), ADD SPATIAL INDEX idx5(c3);
|
ALTER TABLE t1 DROP INDEX idx3, ADD SPATIAL INDEX idx4(c2), ADD SPATIAL INDEX idx5(c3);
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
22
mysql-test/suite/perfschema/r/sxlock_func,debug.rdiff
Normal file
22
mysql-test/suite/perfschema/r/sxlock_func,debug.rdiff
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
@@ -7,7 +7,6 @@
|
||||||
|
WHERE name LIKE 'wait/synch/rwlock/innodb/%'
|
||||||
|
AND name!='wait/synch/rwlock/innodb/btr_search_latch' ORDER BY name;
|
||||||
|
name
|
||||||
|
-wait/synch/rwlock/innodb/dict_operation_lock
|
||||||
|
wait/synch/rwlock/innodb/fil_space_latch
|
||||||
|
wait/synch/rwlock/innodb/lock_latch
|
||||||
|
wait/synch/rwlock/innodb/trx_i_s_cache_lock
|
||||||
|
@@ -19,11 +18,13 @@
|
||||||
|
select name from performance_schema.setup_instruments
|
||||||
|
where name like "wait/synch/sxlock/%" order by name;
|
||||||
|
name
|
||||||
|
+wait/synch/sxlock/innodb/dict_operation_lock
|
||||||
|
wait/synch/sxlock/innodb/index_tree_rw_lock
|
||||||
|
SELECT DISTINCT name FROM performance_schema.rwlock_instances
|
||||||
|
WHERE name LIKE 'wait/synch/sxlock/innodb/%'
|
||||||
|
ORDER BY name;
|
||||||
|
name
|
||||||
|
+wait/synch/sxlock/innodb/dict_operation_lock
|
||||||
|
wait/synch/sxlock/innodb/index_tree_rw_lock
|
||||||
|
create table t1(a int) engine=innodb;
|
||||||
|
begin;
|
@ -5,6 +5,7 @@
|
|||||||
--source include/not_embedded.inc
|
--source include/not_embedded.inc
|
||||||
--source include/have_perfschema.inc
|
--source include/have_perfschema.inc
|
||||||
--source include/have_innodb.inc
|
--source include/have_innodb.inc
|
||||||
|
--source include/maybe_debug.inc
|
||||||
|
|
||||||
UPDATE performance_schema.setup_instruments SET enabled = 'NO', timed = 'YES';
|
UPDATE performance_schema.setup_instruments SET enabled = 'NO', timed = 'YES';
|
||||||
|
|
||||||
|
@ -270,16 +270,12 @@ Variable_name Value
|
|||||||
Rpl_semi_sync_master_clients 1
|
Rpl_semi_sync_master_clients 1
|
||||||
# Test failure of select error .
|
# Test failure of select error .
|
||||||
SET GLOBAL debug = 'd,rpl_semisync_simulate_select_error';
|
SET GLOBAL debug = 'd,rpl_semisync_simulate_select_error';
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
INSERT INTO t1 VALUES(3);
|
INSERT INTO t1 VALUES(3);
|
||||||
connection slave;
|
connection slave;
|
||||||
connection con1;
|
connection con1;
|
||||||
# Test failure of pthread_create
|
# Test failure of pthread_create
|
||||||
SET GLOBAL rpl_semi_sync_master_enabled = 0;
|
SET GLOBAL rpl_semi_sync_master_enabled = 0;
|
||||||
SET GLOBAL debug = 'd,rpl_semisync_simulate_create_thread_failure';
|
SET GLOBAL debug = 'd,rpl_semisync_simulate_create_thread_failure';
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
SET GLOBAL rpl_semi_sync_master_enabled= ON;
|
SET GLOBAL rpl_semi_sync_master_enabled= ON;
|
||||||
# Test failure of pthread_join
|
# Test failure of pthread_join
|
||||||
SET GLOBAL rpl_semi_sync_master_enabled= OFF;
|
SET GLOBAL rpl_semi_sync_master_enabled= OFF;
|
||||||
@ -287,8 +283,6 @@ SET GLOBAL rpl_semi_sync_master_enabled= OFF;
|
|||||||
# Failure on registering semisync slave
|
# Failure on registering semisync slave
|
||||||
#
|
#
|
||||||
SET GLOBAL debug= 'd,rpl_semisync_simulate_add_slave_failure';
|
SET GLOBAL debug= 'd,rpl_semisync_simulate_add_slave_failure';
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
SET GLOBAL rpl_semi_sync_master_enabled= ON;
|
SET GLOBAL rpl_semi_sync_master_enabled= ON;
|
||||||
connection slave;
|
connection slave;
|
||||||
STOP SLAVE IO_THREAD;
|
STOP SLAVE IO_THREAD;
|
||||||
@ -297,8 +291,6 @@ START SLAVE IO_THREAD;
|
|||||||
include/wait_for_slave_io_to_start.inc
|
include/wait_for_slave_io_to_start.inc
|
||||||
connection con1;
|
connection con1;
|
||||||
SET GLOBAL debug='';
|
SET GLOBAL debug='';
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
connection slave;
|
connection slave;
|
||||||
START SLAVE IO_THREAD;
|
START SLAVE IO_THREAD;
|
||||||
include/wait_for_slave_io_to_start.inc
|
include/wait_for_slave_io_to_start.inc
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
set session debug="L";
|
set session debug="L";
|
||||||
Warnings:
|
|
||||||
Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead
|
|
||||||
select @@global.debug="1";
|
select @@global.debug="1";
|
||||||
@@global.debug="1"
|
@@global.debug="1"
|
||||||
0
|
0
|
||||||
|
@ -38,7 +38,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
|||||||
DEFAULT_VALUE
|
DEFAULT_VALUE
|
||||||
VARIABLE_SCOPE SESSION
|
VARIABLE_SCOPE SESSION
|
||||||
VARIABLE_TYPE VARCHAR
|
VARIABLE_TYPE VARCHAR
|
||||||
VARIABLE_COMMENT Built-in DBUG debugger
|
VARIABLE_COMMENT Built-in DBUG debugger. Alias for --debug
|
||||||
NUMERIC_MIN_VALUE NULL
|
NUMERIC_MIN_VALUE NULL
|
||||||
NUMERIC_MAX_VALUE NULL
|
NUMERIC_MAX_VALUE NULL
|
||||||
NUMERIC_BLOCK_SIZE NULL
|
NUMERIC_BLOCK_SIZE NULL
|
||||||
|
@ -2284,6 +2284,81 @@ Warnings:
|
|||||||
Warning 1292 Incorrect inet6 value: ''
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# MDEV-32879 Server crash in my_decimal::operator= or unexpected ER_DUP_ENTRY upon comparison with INET6 and similar types
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
|
||||||
|
SELECT c + (b = a) AS f, GROUP_CONCAT(c) FROM t1 GROUP BY f;
|
||||||
|
f GROUP_CONCAT(c)
|
||||||
|
NULL 2000-01-01 00:00:00.000000,1900-01-01 00:00:00.000000
|
||||||
|
Warnings:
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
|
||||||
|
SELECT c + (b = a) AS f, COUNT(c) FROM t1 GROUP BY f;
|
||||||
|
f COUNT(c)
|
||||||
|
NULL 2
|
||||||
|
Warnings:
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
|
||||||
|
SELECT c + (b = a) AS f FROM t1 ORDER BY f;
|
||||||
|
f
|
||||||
|
NULL
|
||||||
|
NULL
|
||||||
|
Warnings:
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES ('','::'),('','::');
|
||||||
|
SELECT 1.00 + (b = a) AS f FROM t1 ORDER BY f;
|
||||||
|
f
|
||||||
|
NULL
|
||||||
|
NULL
|
||||||
|
Warnings:
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
SELECT 1.00 + (b BETWEEN a AND '') AS f FROM t1 ORDER BY f;
|
||||||
|
f
|
||||||
|
NULL
|
||||||
|
NULL
|
||||||
|
Warnings:
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
SELECT 1.00 + (b IN (a,'')) AS f FROM t1 ORDER BY f;
|
||||||
|
f
|
||||||
|
NULL
|
||||||
|
NULL
|
||||||
|
Warnings:
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
Warning 1292 Incorrect inet6 value: ''
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
# MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string
|
# MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string
|
||||||
#
|
#
|
||||||
SET sql_mode='';
|
SET sql_mode='';
|
||||||
|
@ -1675,6 +1675,32 @@ INSERT INTO t1 VALUES ('::');
|
|||||||
SELECT * FROM t1 WHERE a IN ('','::1');
|
SELECT * FROM t1 WHERE a IN ('','::1');
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-32879 Server crash in my_decimal::operator= or unexpected ER_DUP_ENTRY upon comparison with INET6 and similar types
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
|
||||||
|
SELECT c + (b = a) AS f, GROUP_CONCAT(c) FROM t1 GROUP BY f;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
|
||||||
|
SELECT c + (b = a) AS f, COUNT(c) FROM t1 GROUP BY f;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL, c DATETIME(6) NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES ('','::','2000-01-01'),('','::','1900-01-01');
|
||||||
|
SELECT c + (b = a) AS f FROM t1 ORDER BY f;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
CREATE OR REPLACE TABLE t1 (a CHAR(36) NOT NULL, b INET6 NOT NULL);
|
||||||
|
INSERT INTO t1 VALUES ('','::'),('','::');
|
||||||
|
SELECT 1.00 + (b = a) AS f FROM t1 ORDER BY f;
|
||||||
|
SELECT 1.00 + (b BETWEEN a AND '') AS f FROM t1 ORDER BY f;
|
||||||
|
SELECT 1.00 + (b IN (a,'')) AS f FROM t1 ORDER BY f;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string
|
--echo # MDEV-22256 Assertion `length == pack_length()' failed in Field_timestamp_with_dec::sort_string
|
||||||
--echo #
|
--echo #
|
||||||
|
@ -229,11 +229,11 @@ sub setpwd
|
|||||||
{
|
{
|
||||||
$pass = "PASSWORD(". $dbh->quote($pass) . ")";
|
$pass = "PASSWORD(". $dbh->quote($pass) . ")";
|
||||||
}
|
}
|
||||||
my $uh= "$user@$host";
|
my $uh= $user."@".$host;
|
||||||
my $sth = $dbh->prepare("set password for $uh =$pass") || die $dbh->errstr;
|
my $sth = $dbh->prepare("set password for $uh =$pass") || die $dbh->errstr;
|
||||||
$sth->execute || die $dbh->errstr;
|
$sth->execute || die $dbh->errstr;
|
||||||
$sth->finish;
|
$sth->finish;
|
||||||
print "The password is set for user $user.\n\n";
|
print "The password is set for user $uh.\n\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,40 +457,6 @@ void Item_bool_func::raise_note_if_key_become_unused(THD *thd, const Item_args &
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp)
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(arg_count >= 2); // Item_func_nullif has arg_count == 3
|
|
||||||
|
|
||||||
if (args[0]->cmp_type() == STRING_RESULT &&
|
|
||||||
args[1]->cmp_type() == STRING_RESULT)
|
|
||||||
{
|
|
||||||
CHARSET_INFO *tmp;
|
|
||||||
/*
|
|
||||||
Use charset narrowing only for equalities, as that would allow
|
|
||||||
to construct ref access.
|
|
||||||
Non-equality comparisons with constants work without charset narrowing,
|
|
||||||
the constant gets converted.
|
|
||||||
Non-equality comparisons with non-constants would need narrowing to
|
|
||||||
enable range optimizer to handle e.g.
|
|
||||||
t1.mb3key_col <= const_table.mb4_col
|
|
||||||
But this doesn't look important.
|
|
||||||
*/
|
|
||||||
bool allow_narrowing= MY_TEST(functype()==Item_func::EQ_FUNC ||
|
|
||||||
functype()==Item_func::EQUAL_FUNC);
|
|
||||||
|
|
||||||
if (agg_arg_charsets_for_comparison(&tmp, &args[0], &args[1],
|
|
||||||
allow_narrowing))
|
|
||||||
return true;
|
|
||||||
cmp->m_compare_collation= tmp;
|
|
||||||
}
|
|
||||||
// Convert constants when compared to int/year field
|
|
||||||
DBUG_ASSERT(functype() != LIKE_FUNC);
|
|
||||||
convert_const_compared_to_int_field(thd);
|
|
||||||
|
|
||||||
return cmp->set_cmp_func(thd, this, &args[0], &args[1], true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Comparison operators remove arguments' dependency on PAD_CHAR_TO_FULL_LENGTH
|
Comparison operators remove arguments' dependency on PAD_CHAR_TO_FULL_LENGTH
|
||||||
in case of PAD SPACE comparison collations: trailing spaces do not affect
|
in case of PAD SPACE comparison collations: trailing spaces do not affect
|
||||||
@ -519,8 +485,15 @@ bool Item_bool_rowready_func2::fix_length_and_dec(THD *thd)
|
|||||||
if (!args[0] || !args[1])
|
if (!args[0] || !args[1])
|
||||||
return FALSE;
|
return FALSE;
|
||||||
Item_args old_args(args[0], args[1]);
|
Item_args old_args(args[0], args[1]);
|
||||||
if (setup_args_and_comparator(thd, &cmp))
|
convert_const_compared_to_int_field(thd);
|
||||||
|
Type_handler_hybrid_field_type tmp;
|
||||||
|
if (tmp.aggregate_for_comparison(func_name_cstring(), args, 2, false) ||
|
||||||
|
tmp.type_handler()->Item_bool_rowready_func2_fix_length_and_dec(thd,
|
||||||
|
this))
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(thd->is_error());
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
raise_note_if_key_become_unused(thd, old_args);
|
raise_note_if_key_become_unused(thd, old_args);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -540,21 +513,14 @@ bool Item_bool_rowready_func2::fix_length_and_dec(THD *thd)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int Arg_comparator::set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
|
int Arg_comparator::set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
|
||||||
|
const Type_handler *compare_handler,
|
||||||
Item **a1, Item **a2)
|
Item **a1, Item **a2)
|
||||||
{
|
{
|
||||||
owner= owner_arg;
|
owner= owner_arg;
|
||||||
set_null= set_null && owner_arg;
|
set_null= set_null && owner_arg;
|
||||||
a= a1;
|
a= a1;
|
||||||
b= a2;
|
b= a2;
|
||||||
Item *tmp_args[2]= {*a1, *a2};
|
m_compare_handler= compare_handler;
|
||||||
Type_handler_hybrid_field_type tmp;
|
|
||||||
if (tmp.aggregate_for_comparison(owner_arg->func_name_cstring(), tmp_args, 2,
|
|
||||||
false))
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(thd->is_error());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
m_compare_handler= tmp.type_handler();
|
|
||||||
return m_compare_handler->set_comparator_func(thd, this);
|
return m_compare_handler->set_comparator_func(thd, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,6 +571,14 @@ bool Arg_comparator::set_cmp_func_string(THD *thd)
|
|||||||
We must set cmp_collation here as we may be called from for an automatic
|
We must set cmp_collation here as we may be called from for an automatic
|
||||||
generated item, like in natural join.
|
generated item, like in natural join.
|
||||||
Allow reinterpted superset as subset.
|
Allow reinterpted superset as subset.
|
||||||
|
Use charset narrowing only for equalities, as that would allow
|
||||||
|
to construct ref access.
|
||||||
|
Non-equality comparisons with constants work without charset narrowing,
|
||||||
|
the constant gets converted.
|
||||||
|
Non-equality comparisons with non-constants would need narrowing to
|
||||||
|
enable range optimizer to handle e.g.
|
||||||
|
t1.mb3key_col <= const_table.mb4_col
|
||||||
|
But this doesn't look important.
|
||||||
*/
|
*/
|
||||||
bool allow_narrowing= false;
|
bool allow_narrowing= false;
|
||||||
if (owner->type() == Item::FUNC_ITEM)
|
if (owner->type() == Item::FUNC_ITEM)
|
||||||
@ -2812,8 +2786,9 @@ Item_func_nullif::fix_length_and_dec(THD *thd)
|
|||||||
fix_char_length(args[2]->max_char_length());
|
fix_char_length(args[2]->max_char_length());
|
||||||
set_maybe_null();
|
set_maybe_null();
|
||||||
m_arg0= args[0];
|
m_arg0= args[0];
|
||||||
if (setup_args_and_comparator(thd, &cmp))
|
convert_const_compared_to_int_field(thd);
|
||||||
return TRUE;
|
if (cmp.set_cmp_func(thd, this, &args[0], &args[1], true/*set_null*/))
|
||||||
|
return true;
|
||||||
/*
|
/*
|
||||||
A special code for EXECUTE..PREPARE.
|
A special code for EXECUTE..PREPARE.
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ class Arg_comparator: public Sql_alloc
|
|||||||
// when one of arguments is NULL.
|
// when one of arguments is NULL.
|
||||||
|
|
||||||
int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
|
int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
|
||||||
|
const Type_handler *compare_handler,
|
||||||
Item **a1, Item **a2);
|
Item **a1, Item **a2);
|
||||||
|
|
||||||
int compare_not_null_values(longlong val1, longlong val2)
|
int compare_not_null_values(longlong val1, longlong val2)
|
||||||
@ -95,11 +96,24 @@ public:
|
|||||||
bool set_cmp_func_decimal(THD *thd);
|
bool set_cmp_func_decimal(THD *thd);
|
||||||
|
|
||||||
inline int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
|
inline int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
|
||||||
|
const Type_handler *compare_handler,
|
||||||
Item **a1, Item **a2, bool set_null_arg)
|
Item **a1, Item **a2, bool set_null_arg)
|
||||||
{
|
{
|
||||||
set_null= set_null_arg;
|
set_null= set_null_arg;
|
||||||
return set_cmp_func(thd, owner_arg, a1, a2);
|
return set_cmp_func(thd, owner_arg, compare_handler, a1, a2);
|
||||||
}
|
}
|
||||||
|
int set_cmp_func(THD *thd, Item_func_or_sum *owner_arg,
|
||||||
|
Item **a1, Item **a2, bool set_null_arg)
|
||||||
|
{
|
||||||
|
Item *tmp_args[2]= { *a1, *a2 };
|
||||||
|
Type_handler_hybrid_field_type tmp;
|
||||||
|
if (tmp.aggregate_for_comparison(owner_arg->func_name_cstring(),
|
||||||
|
tmp_args, 2, false))
|
||||||
|
return 1;
|
||||||
|
return set_cmp_func(thd, owner_arg, tmp.type_handler(),
|
||||||
|
a1, a2, set_null_arg);
|
||||||
|
}
|
||||||
|
|
||||||
inline int compare() { return (this->*func)(); }
|
inline int compare() { return (this->*func)(); }
|
||||||
|
|
||||||
int compare_string(); // compare args[0] & args[1]
|
int compare_string(); // compare args[0] & args[1]
|
||||||
@ -561,9 +575,17 @@ public:
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
bool fix_length_and_dec(THD *thd) override;
|
bool fix_length_and_dec(THD *thd) override;
|
||||||
|
bool fix_length_and_dec_generic(THD *thd,
|
||||||
|
const Type_handler *compare_handler)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(args == tmp_arg);
|
||||||
|
return cmp.set_cmp_func(thd, this, compare_handler,
|
||||||
|
tmp_arg, tmp_arg + 1, true/*set_null*/);
|
||||||
|
}
|
||||||
int set_cmp_func(THD *thd)
|
int set_cmp_func(THD *thd)
|
||||||
{
|
{
|
||||||
return cmp.set_cmp_func(thd, this, tmp_arg, tmp_arg + 1, true);
|
DBUG_ASSERT(args == tmp_arg);
|
||||||
|
return cmp.set_cmp_func(thd, this, tmp_arg, tmp_arg + 1, true/*set_null*/);
|
||||||
}
|
}
|
||||||
CHARSET_INFO *compare_collation() const override
|
CHARSET_INFO *compare_collation() const override
|
||||||
{ return cmp.compare_collation(); }
|
{ return cmp.compare_collation(); }
|
||||||
|
@ -388,15 +388,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void convert_const_compared_to_int_field(THD *thd);
|
void convert_const_compared_to_int_field(THD *thd);
|
||||||
/**
|
|
||||||
Prepare arguments and setup a comparator.
|
|
||||||
Used in Item_func_xxx with two arguments and a comparator,
|
|
||||||
e.g. Item_bool_func2 and Item_func_nullif.
|
|
||||||
args[0] or args[1] can be modified:
|
|
||||||
- converted to character set and collation of the operation
|
|
||||||
- or replaced to an Item_int_with_ref
|
|
||||||
*/
|
|
||||||
bool setup_args_and_comparator(THD *thd, Arg_comparator *cmp);
|
|
||||||
Item_func *get_item_func() override { return this; }
|
Item_func *get_item_func() override { return this; }
|
||||||
bool is_simplified_cond_processor(void *arg) override
|
bool is_simplified_cond_processor(void *arg) override
|
||||||
{ return const_item() && !val_int(); }
|
{ return const_item() && !val_int(); }
|
||||||
|
@ -1296,9 +1296,14 @@ void Item_sum_min_max::setup_hybrid(THD *thd, Item *item, Item *value_arg)
|
|||||||
/* Don't cache value, as it will change */
|
/* Don't cache value, as it will change */
|
||||||
if (!item->const_item())
|
if (!item->const_item())
|
||||||
arg_cache->set_used_tables(RAND_TABLE_BIT);
|
arg_cache->set_used_tables(RAND_TABLE_BIT);
|
||||||
|
DBUG_ASSERT(item->type_handler_for_comparison() ==
|
||||||
|
value->type_handler_for_comparison());
|
||||||
|
DBUG_ASSERT(item->type_handler_for_comparison() ==
|
||||||
|
arg_cache->type_handler_for_comparison());
|
||||||
cmp= new (thd->mem_root) Arg_comparator();
|
cmp= new (thd->mem_root) Arg_comparator();
|
||||||
if (cmp)
|
if (cmp)
|
||||||
cmp->set_cmp_func(thd, this, (Item**)&arg_cache, (Item**)&value, FALSE);
|
cmp->set_cmp_func(thd, this, item->type_handler_for_comparison(),
|
||||||
|
(Item**)&arg_cache, (Item**)&value, FALSE);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5668,6 +5668,14 @@ Type_handler_string_result::Item_func_hybrid_field_type_get_date(
|
|||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
|
bool Type_handler::Item_bool_rowready_func2_fix_length_and_dec(THD *thd,
|
||||||
|
Item_bool_rowready_func2 *func) const
|
||||||
|
{
|
||||||
|
return func->fix_length_and_dec_generic(thd, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
bool Type_handler_numeric::
|
bool Type_handler_numeric::
|
||||||
Item_func_between_fix_length_and_dec(Item_func_between *func) const
|
Item_func_between_fix_length_and_dec(Item_func_between *func) const
|
||||||
{
|
{
|
||||||
|
@ -55,6 +55,7 @@ class Item_hybrid_func;
|
|||||||
class Item_func_min_max;
|
class Item_func_min_max;
|
||||||
class Item_func_hybrid_field_type;
|
class Item_func_hybrid_field_type;
|
||||||
class Item_bool_func2;
|
class Item_bool_func2;
|
||||||
|
class Item_bool_rowready_func2;
|
||||||
class Item_func_between;
|
class Item_func_between;
|
||||||
class Item_func_in;
|
class Item_func_in;
|
||||||
class Item_func_round;
|
class Item_func_round;
|
||||||
@ -4257,6 +4258,8 @@ public:
|
|||||||
}
|
}
|
||||||
virtual bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr,
|
virtual bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr,
|
||||||
Item *a, Item *b) const= 0;
|
Item *a, Item *b) const= 0;
|
||||||
|
virtual bool Item_bool_rowready_func2_fix_length_and_dec(THD *thd,
|
||||||
|
Item_bool_rowready_func2 *func) const;
|
||||||
virtual bool Item_hybrid_func_fix_attributes(THD *thd,
|
virtual bool Item_hybrid_func_fix_attributes(THD *thd,
|
||||||
const LEX_CSTRING &name,
|
const LEX_CSTRING &name,
|
||||||
Type_handler_hybrid_field_type *,
|
Type_handler_hybrid_field_type *,
|
||||||
|
@ -136,6 +136,21 @@ public:
|
|||||||
return Fbt_null(item, false).is_null();
|
return Fbt_null(item, false).is_null();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check at fix_fields() time if any of the items can return a nullable
|
||||||
|
value on conversion to Fbt.
|
||||||
|
*/
|
||||||
|
static bool fix_fields_maybe_null_on_conversion_to_fbt(Item **items,
|
||||||
|
uint count)
|
||||||
|
{
|
||||||
|
for (uint i= 0; i < count; i++)
|
||||||
|
{
|
||||||
|
if (Fbt::fix_fields_maybe_null_on_conversion_to_fbt(items[i]))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Fbt(Item *item, bool *error, bool warn= true)
|
Fbt(Item *item, bool *error, bool warn= true)
|
||||||
@ -1534,6 +1549,16 @@ public:
|
|||||||
Fbt_null na(a), nb(b);
|
Fbt_null na(a), nb(b);
|
||||||
return !na.is_null() && !nb.is_null() && !na.cmp(nb);
|
return !na.is_null() && !nb.is_null() && !na.cmp(nb);
|
||||||
}
|
}
|
||||||
|
bool Item_bool_rowready_func2_fix_length_and_dec(THD *thd,
|
||||||
|
Item_bool_rowready_func2 *func) const override
|
||||||
|
{
|
||||||
|
if (Type_handler::Item_bool_rowready_func2_fix_length_and_dec(thd, func))
|
||||||
|
return true;
|
||||||
|
if (!func->maybe_null() &&
|
||||||
|
Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(), 2))
|
||||||
|
func->set_maybe_null();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name,
|
bool Item_hybrid_func_fix_attributes(THD *thd, const LEX_CSTRING &name,
|
||||||
Type_handler_hybrid_field_type *h,
|
Type_handler_hybrid_field_type *h,
|
||||||
Type_all_attributes *attr,
|
Type_all_attributes *attr,
|
||||||
@ -1715,6 +1740,9 @@ public:
|
|||||||
|
|
||||||
bool Item_func_between_fix_length_and_dec(Item_func_between *func) const override
|
bool Item_func_between_fix_length_and_dec(Item_func_between *func) const override
|
||||||
{
|
{
|
||||||
|
if (!func->maybe_null() &&
|
||||||
|
Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(), 3))
|
||||||
|
func->set_maybe_null();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
longlong Item_func_between_val_int(Item_func_between *func) const override
|
longlong Item_func_between_val_int(Item_func_between *func) const override
|
||||||
@ -1737,6 +1765,10 @@ public:
|
|||||||
Item_func_in *func)
|
Item_func_in *func)
|
||||||
const override
|
const override
|
||||||
{
|
{
|
||||||
|
if (!func->maybe_null() &&
|
||||||
|
Fbt::fix_fields_maybe_null_on_conversion_to_fbt(func->arguments(),
|
||||||
|
func->argument_count()))
|
||||||
|
func->set_maybe_null();
|
||||||
if (func->compatible_types_scalar_bisection_possible())
|
if (func->compatible_types_scalar_bisection_possible())
|
||||||
{
|
{
|
||||||
return func->value_list_convert_const_to_int(thd) ||
|
return func->value_list_convert_const_to_int(thd) ||
|
||||||
|
@ -1049,11 +1049,10 @@ static Sys_var_charptr_fscs Sys_datadir(
|
|||||||
static Sys_var_dbug Sys_dbug(
|
static Sys_var_dbug Sys_dbug(
|
||||||
"debug", "Built-in DBUG debugger", sys_var::SESSION,
|
"debug", "Built-in DBUG debugger", sys_var::SESSION,
|
||||||
CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG,
|
CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG,
|
||||||
ON_CHECK(check_has_super), ON_UPDATE(0),
|
ON_CHECK(check_has_super));
|
||||||
DEPRECATED("'@@debug_dbug'")); // since 5.5.37
|
|
||||||
|
|
||||||
static Sys_var_dbug Sys_debug_dbug(
|
static Sys_var_dbug Sys_debug_dbug(
|
||||||
"debug_dbug", "Built-in DBUG debugger", sys_var::SESSION,
|
"debug_dbug", "Built-in DBUG debugger. Alias for --debug", sys_var::SESSION,
|
||||||
CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG,
|
CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG,
|
||||||
ON_CHECK(check_has_super));
|
ON_CHECK(check_has_super));
|
||||||
#endif
|
#endif
|
||||||
|
@ -788,7 +788,8 @@ static rec_offs *btr_page_get_parent(rec_offs *offsets, mem_heap_t *heap,
|
|||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
Returns the upper level node pointer to a page. It is assumed that mtr holds
|
Returns the upper level node pointer to a page. It is assumed that mtr holds
|
||||||
an x-latch on the tree.
|
an x-latch on the tree.
|
||||||
@return rec_get_offsets() of the node pointer record */
|
@return rec_get_offsets() of the node pointer record
|
||||||
|
@retval nullptr on corruption */
|
||||||
static
|
static
|
||||||
rec_offs*
|
rec_offs*
|
||||||
btr_page_get_father_block(
|
btr_page_get_father_block(
|
||||||
@ -2374,6 +2375,11 @@ btr_attach_half_pages(
|
|||||||
offsets = btr_page_get_father_block(nullptr, heap, mtr,
|
offsets = btr_page_get_father_block(nullptr, heap, mtr,
|
||||||
&cursor);
|
&cursor);
|
||||||
|
|
||||||
|
if (UNIV_UNLIKELY(!offsets)) {
|
||||||
|
mem_heap_free(heap);
|
||||||
|
return DB_CORRUPTION;
|
||||||
|
}
|
||||||
|
|
||||||
/* Replace the address of the old child node (= page) with the
|
/* Replace the address of the old child node (= page) with the
|
||||||
address of the new lower half */
|
address of the new lower half */
|
||||||
|
|
||||||
@ -3247,6 +3253,14 @@ btr_lift_page_up(
|
|||||||
offsets = btr_page_get_father_block(offsets, heap,
|
offsets = btr_page_get_father_block(offsets, heap,
|
||||||
mtr, &cursor);
|
mtr, &cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UNIV_UNLIKELY(!offsets)) {
|
||||||
|
parent_corrupted:
|
||||||
|
mem_heap_free(heap);
|
||||||
|
*err = DB_CORRUPTION;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
father_block = btr_cur_get_block(&cursor);
|
father_block = btr_cur_get_block(&cursor);
|
||||||
father_page_zip = buf_block_get_page_zip(father_block);
|
father_page_zip = buf_block_get_page_zip(father_block);
|
||||||
|
|
||||||
@ -3272,6 +3286,10 @@ btr_lift_page_up(
|
|||||||
&cursor);
|
&cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UNIV_UNLIKELY(!offsets)) {
|
||||||
|
goto parent_corrupted;
|
||||||
|
}
|
||||||
|
|
||||||
blocks[n_blocks++] = b = btr_cur_get_block(&cursor);
|
blocks[n_blocks++] = b = btr_cur_get_block(&cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3484,6 +3502,10 @@ get_offsets:
|
|||||||
NULL, heap, mtr, &father_cursor);
|
NULL, heap, mtr, &father_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UNIV_UNLIKELY(!offsets)) {
|
||||||
|
goto corrupted;
|
||||||
|
}
|
||||||
|
|
||||||
if (adjust) {
|
if (adjust) {
|
||||||
nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
|
nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
|
||||||
if (UNIV_UNLIKELY(!nth_rec || nth_rec == ULINT_UNDEFINED)) {
|
if (UNIV_UNLIKELY(!nth_rec || nth_rec == ULINT_UNDEFINED)) {
|
||||||
|
@ -2414,14 +2414,21 @@ lookup:
|
|||||||
|
|
||||||
if (discard_attempted || !bpage->frame)
|
if (discard_attempted || !bpage->frame)
|
||||||
{
|
{
|
||||||
/* Even when we are holding a hash_lock, it should be
|
const bool got_s_latch= bpage->lock.s_lock_try();
|
||||||
acceptable to wait for a page S-latch here, because
|
|
||||||
buf_page_t::read_complete() will not wait for buf_pool.mutex,
|
|
||||||
and because S-latch would not conflict with a U-latch
|
|
||||||
that would be protecting buf_page_t::write_complete(). */
|
|
||||||
bpage->lock.s_lock();
|
|
||||||
hash_lock.unlock_shared();
|
hash_lock.unlock_shared();
|
||||||
|
if (UNIV_LIKELY(got_s_latch))
|
||||||
break;
|
break;
|
||||||
|
/* We may fail to acquire bpage->lock because
|
||||||
|
buf_page_t::read_complete() may be invoking
|
||||||
|
buf_pool_t::corrupted_evict() on this block, which it would
|
||||||
|
hold an exclusive latch on.
|
||||||
|
|
||||||
|
Let us aqcuire and release buf_pool.mutex to ensure that any
|
||||||
|
buf_pool_t::corrupted_evict() will proceed before we reacquire
|
||||||
|
the hash_lock that it could be waiting for. */
|
||||||
|
mysql_mutex_lock(&buf_pool.mutex);
|
||||||
|
mysql_mutex_unlock(&buf_pool.mutex);
|
||||||
|
goto lookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_lock.unlock_shared();
|
hash_lock.unlock_shared();
|
||||||
|
@ -958,11 +958,12 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line))
|
|||||||
if (latch_ex_wait_start.compare_exchange_strong
|
if (latch_ex_wait_start.compare_exchange_strong
|
||||||
(old, now, std::memory_order_relaxed, std::memory_order_relaxed))
|
(old, now, std::memory_order_relaxed, std::memory_order_relaxed))
|
||||||
{
|
{
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
latch.x_lock(SRW_LOCK_ARGS(file, line));
|
||||||
|
#else
|
||||||
latch.wr_lock(SRW_LOCK_ARGS(file, line));
|
latch.wr_lock(SRW_LOCK_ARGS(file, line));
|
||||||
|
#endif
|
||||||
latch_ex_wait_start.store(0, std::memory_order_relaxed);
|
latch_ex_wait_start.store(0, std::memory_order_relaxed);
|
||||||
ut_ad(!latch_readers);
|
|
||||||
ut_ad(!latch_ex);
|
|
||||||
ut_d(latch_ex= pthread_self());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -977,33 +978,39 @@ void dict_sys_t::lock_wait(SRW_LOCK_ARGS(const char *file, unsigned line))
|
|||||||
if (waited > threshold / 4)
|
if (waited > threshold / 4)
|
||||||
ib::warn() << "A long wait (" << waited
|
ib::warn() << "A long wait (" << waited
|
||||||
<< " seconds) was observed for dict_sys.latch";
|
<< " seconds) was observed for dict_sys.latch";
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
latch.x_lock(SRW_LOCK_ARGS(file, line));
|
||||||
|
#else
|
||||||
latch.wr_lock(SRW_LOCK_ARGS(file, line));
|
latch.wr_lock(SRW_LOCK_ARGS(file, line));
|
||||||
ut_ad(!latch_readers);
|
#endif
|
||||||
ut_ad(!latch_ex);
|
|
||||||
ut_d(latch_ex= pthread_self());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIV_PFS_RWLOCK
|
#ifdef UNIV_PFS_RWLOCK
|
||||||
ATTRIBUTE_NOINLINE void dict_sys_t::unlock()
|
ATTRIBUTE_NOINLINE void dict_sys_t::unlock()
|
||||||
{
|
{
|
||||||
ut_ad(latch_ex == pthread_self());
|
# ifdef UNIV_DEBUG
|
||||||
ut_ad(!latch_readers);
|
latch.x_unlock();
|
||||||
ut_d(latch_ex= 0);
|
# else
|
||||||
latch.wr_unlock();
|
latch.wr_unlock();
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ATTRIBUTE_NOINLINE void dict_sys_t::freeze(const char *file, unsigned line)
|
ATTRIBUTE_NOINLINE void dict_sys_t::freeze(const char *file, unsigned line)
|
||||||
{
|
{
|
||||||
|
# ifdef UNIV_DEBUG
|
||||||
|
latch.s_lock(file, line);
|
||||||
|
# else
|
||||||
latch.rd_lock(file, line);
|
latch.rd_lock(file, line);
|
||||||
ut_ad(!latch_ex);
|
# endif
|
||||||
ut_d(latch_readers++);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ATTRIBUTE_NOINLINE void dict_sys_t::unfreeze()
|
ATTRIBUTE_NOINLINE void dict_sys_t::unfreeze()
|
||||||
{
|
{
|
||||||
ut_ad(!latch_ex);
|
# ifdef UNIV_DEBUG
|
||||||
ut_ad(latch_readers--);
|
latch.s_unlock();
|
||||||
|
# else
|
||||||
latch.rd_unlock();
|
latch.rd_unlock();
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
#endif /* UNIV_PFS_RWLOCK */
|
#endif /* UNIV_PFS_RWLOCK */
|
||||||
|
|
||||||
@ -4511,7 +4518,11 @@ void dict_sys_t::close()
|
|||||||
temp_id_hash.free();
|
temp_id_hash.free();
|
||||||
|
|
||||||
unlock();
|
unlock();
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
|
latch.free();
|
||||||
|
#else
|
||||||
latch.destroy();
|
latch.destroy();
|
||||||
|
#endif
|
||||||
|
|
||||||
mysql_mutex_destroy(&dict_foreign_err_mutex);
|
mysql_mutex_destroy(&dict_foreign_err_mutex);
|
||||||
|
|
||||||
|
@ -580,7 +580,13 @@ static PSI_rwlock_info all_innodb_rwlocks[] =
|
|||||||
# ifdef BTR_CUR_HASH_ADAPT
|
# ifdef BTR_CUR_HASH_ADAPT
|
||||||
{ &btr_search_latch_key, "btr_search_latch", 0 },
|
{ &btr_search_latch_key, "btr_search_latch", 0 },
|
||||||
# endif
|
# endif
|
||||||
{ &dict_operation_lock_key, "dict_operation_lock", 0 },
|
{ &dict_operation_lock_key, "dict_operation_lock",
|
||||||
|
# ifdef UNIV_DEBUG
|
||||||
|
PSI_RWLOCK_FLAG_SX
|
||||||
|
# else
|
||||||
|
0
|
||||||
|
# endif
|
||||||
|
},
|
||||||
{ &fil_space_latch_key, "fil_space_latch", 0 },
|
{ &fil_space_latch_key, "fil_space_latch", 0 },
|
||||||
{ &trx_i_s_cache_lock_key, "trx_i_s_cache_lock", 0 },
|
{ &trx_i_s_cache_lock_key, "trx_i_s_cache_lock", 0 },
|
||||||
{ &trx_purge_latch_key, "trx_purge_latch", 0 },
|
{ &trx_purge_latch_key, "trx_purge_latch", 0 },
|
||||||
@ -13456,14 +13462,7 @@ int ha_innobase::delete_table(const char *name)
|
|||||||
/* FOREIGN KEY constraints cannot exist on partitioned tables. */;
|
/* FOREIGN KEY constraints cannot exist on partitioned tables. */;
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
{
|
err= lock_table_children(table, trx);
|
||||||
dict_sys.freeze(SRW_LOCK_CALL);
|
|
||||||
for (const dict_foreign_t* f : table->referenced_set)
|
|
||||||
if (dict_table_t* child= f->foreign_table)
|
|
||||||
if ((err= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS)
|
|
||||||
break;
|
|
||||||
dict_sys.unfreeze();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dict_table_t *table_stats= nullptr, *index_stats= nullptr;
|
dict_table_t *table_stats= nullptr, *index_stats= nullptr;
|
||||||
@ -13861,14 +13860,7 @@ int ha_innobase::truncate()
|
|||||||
dict_table_t *table_stats = nullptr, *index_stats = nullptr;
|
dict_table_t *table_stats = nullptr, *index_stats = nullptr;
|
||||||
MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr;
|
MDL_ticket *mdl_table = nullptr, *mdl_index = nullptr;
|
||||||
|
|
||||||
dberr_t error= DB_SUCCESS;
|
dberr_t error= lock_table_children(ib_table, trx);
|
||||||
|
|
||||||
dict_sys.freeze(SRW_LOCK_CALL);
|
|
||||||
for (const dict_foreign_t *f : ib_table->referenced_set)
|
|
||||||
if (dict_table_t *child= f->foreign_table)
|
|
||||||
if ((error= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS)
|
|
||||||
break;
|
|
||||||
dict_sys.unfreeze();
|
|
||||||
|
|
||||||
if (error == DB_SUCCESS)
|
if (error == DB_SUCCESS)
|
||||||
error= lock_table_for_trx(ib_table, trx, LOCK_X);
|
error= lock_table_for_trx(ib_table, trx, LOCK_X);
|
||||||
@ -14059,16 +14051,7 @@ ha_innobase::rename_table(
|
|||||||
/* There is no need to lock any FOREIGN KEY child tables. */
|
/* There is no need to lock any FOREIGN KEY child tables. */
|
||||||
} else if (dict_table_t *table = dict_table_open_on_name(
|
} else if (dict_table_t *table = dict_table_open_on_name(
|
||||||
norm_from, false, DICT_ERR_IGNORE_FK_NOKEY)) {
|
norm_from, false, DICT_ERR_IGNORE_FK_NOKEY)) {
|
||||||
dict_sys.freeze(SRW_LOCK_CALL);
|
error = lock_table_children(table, trx);
|
||||||
for (const dict_foreign_t* f : table->referenced_set) {
|
|
||||||
if (dict_table_t* child = f->foreign_table) {
|
|
||||||
error = lock_table_for_trx(child, trx, LOCK_X);
|
|
||||||
if (error != DB_SUCCESS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dict_sys.unfreeze();
|
|
||||||
if (error == DB_SUCCESS) {
|
if (error == DB_SUCCESS) {
|
||||||
error = lock_table_for_trx(table, trx, LOCK_X);
|
error = lock_table_for_trx(table, trx, LOCK_X);
|
||||||
}
|
}
|
||||||
@ -15667,15 +15650,17 @@ ha_innobase::extra(
|
|||||||
{
|
{
|
||||||
/* Warning: since it is not sure that MariaDB calls external_lock()
|
/* Warning: since it is not sure that MariaDB calls external_lock()
|
||||||
before calling this function, m_prebuilt->trx can be obsolete! */
|
before calling this function, m_prebuilt->trx can be obsolete! */
|
||||||
trx_t* trx = check_trx_exists(ha_thd());
|
trx_t* trx;
|
||||||
|
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case HA_EXTRA_FLUSH:
|
case HA_EXTRA_FLUSH:
|
||||||
|
(void)check_trx_exists(ha_thd());
|
||||||
if (m_prebuilt->blob_heap) {
|
if (m_prebuilt->blob_heap) {
|
||||||
row_mysql_prebuilt_free_blob_heap(m_prebuilt);
|
row_mysql_prebuilt_free_blob_heap(m_prebuilt);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_RESET_STATE:
|
case HA_EXTRA_RESET_STATE:
|
||||||
|
trx = check_trx_exists(ha_thd());
|
||||||
reset_template();
|
reset_template();
|
||||||
trx->duplicates = 0;
|
trx->duplicates = 0;
|
||||||
stmt_boundary:
|
stmt_boundary:
|
||||||
@ -15684,18 +15669,23 @@ ha_innobase::extra(
|
|||||||
trx->bulk_insert = false;
|
trx->bulk_insert = false;
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_NO_KEYREAD:
|
case HA_EXTRA_NO_KEYREAD:
|
||||||
|
(void)check_trx_exists(ha_thd());
|
||||||
m_prebuilt->read_just_key = 0;
|
m_prebuilt->read_just_key = 0;
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_KEYREAD:
|
case HA_EXTRA_KEYREAD:
|
||||||
|
(void)check_trx_exists(ha_thd());
|
||||||
m_prebuilt->read_just_key = 1;
|
m_prebuilt->read_just_key = 1;
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
|
case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
|
||||||
|
(void)check_trx_exists(ha_thd());
|
||||||
m_prebuilt->keep_other_fields_on_keyread = 1;
|
m_prebuilt->keep_other_fields_on_keyread = 1;
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_INSERT_WITH_UPDATE:
|
case HA_EXTRA_INSERT_WITH_UPDATE:
|
||||||
|
trx = check_trx_exists(ha_thd());
|
||||||
trx->duplicates |= TRX_DUP_IGNORE;
|
trx->duplicates |= TRX_DUP_IGNORE;
|
||||||
goto stmt_boundary;
|
goto stmt_boundary;
|
||||||
case HA_EXTRA_NO_IGNORE_DUP_KEY:
|
case HA_EXTRA_NO_IGNORE_DUP_KEY:
|
||||||
|
trx = check_trx_exists(ha_thd());
|
||||||
trx->duplicates &= ~TRX_DUP_IGNORE;
|
trx->duplicates &= ~TRX_DUP_IGNORE;
|
||||||
if (trx->is_bulk_insert()) {
|
if (trx->is_bulk_insert()) {
|
||||||
/* Allow a subsequent INSERT into an empty table
|
/* Allow a subsequent INSERT into an empty table
|
||||||
@ -15707,9 +15697,11 @@ ha_innobase::extra(
|
|||||||
}
|
}
|
||||||
goto stmt_boundary;
|
goto stmt_boundary;
|
||||||
case HA_EXTRA_WRITE_CAN_REPLACE:
|
case HA_EXTRA_WRITE_CAN_REPLACE:
|
||||||
|
trx = check_trx_exists(ha_thd());
|
||||||
trx->duplicates |= TRX_DUP_REPLACE;
|
trx->duplicates |= TRX_DUP_REPLACE;
|
||||||
goto stmt_boundary;
|
goto stmt_boundary;
|
||||||
case HA_EXTRA_WRITE_CANNOT_REPLACE:
|
case HA_EXTRA_WRITE_CANNOT_REPLACE:
|
||||||
|
trx = check_trx_exists(ha_thd());
|
||||||
trx->duplicates &= ~TRX_DUP_REPLACE;
|
trx->duplicates &= ~TRX_DUP_REPLACE;
|
||||||
if (trx->is_bulk_insert()) {
|
if (trx->is_bulk_insert()) {
|
||||||
/* Allow a subsequent INSERT into an empty table
|
/* Allow a subsequent INSERT into an empty table
|
||||||
@ -15718,6 +15710,7 @@ ha_innobase::extra(
|
|||||||
}
|
}
|
||||||
goto stmt_boundary;
|
goto stmt_boundary;
|
||||||
case HA_EXTRA_BEGIN_ALTER_COPY:
|
case HA_EXTRA_BEGIN_ALTER_COPY:
|
||||||
|
trx = check_trx_exists(ha_thd());
|
||||||
m_prebuilt->table->skip_alter_undo = 1;
|
m_prebuilt->table->skip_alter_undo = 1;
|
||||||
if (m_prebuilt->table->is_temporary()
|
if (m_prebuilt->table->is_temporary()
|
||||||
|| !m_prebuilt->table->versioned_by_id()) {
|
|| !m_prebuilt->table->versioned_by_id()) {
|
||||||
@ -15730,6 +15723,7 @@ ha_innobase::extra(
|
|||||||
.first->second.set_versioned(0);
|
.first->second.set_versioned(0);
|
||||||
break;
|
break;
|
||||||
case HA_EXTRA_END_ALTER_COPY:
|
case HA_EXTRA_END_ALTER_COPY:
|
||||||
|
trx = check_trx_exists(ha_thd());
|
||||||
m_prebuilt->table->skip_alter_undo = 0;
|
m_prebuilt->table->skip_alter_undo = 0;
|
||||||
if (!m_prebuilt->table->is_temporary()
|
if (!m_prebuilt->table->is_temporary()
|
||||||
&& !high_level_read_only) {
|
&& !high_level_read_only) {
|
||||||
|
@ -11222,16 +11222,7 @@ ha_innobase::commit_inplace_alter_table(
|
|||||||
fts_optimize_remove_table(ctx->old_table);
|
fts_optimize_remove_table(ctx->old_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
dict_sys.freeze(SRW_LOCK_CALL);
|
error = lock_table_children(ctx->old_table, trx);
|
||||||
for (auto f : ctx->old_table->referenced_set) {
|
|
||||||
if (dict_table_t* child = f->foreign_table) {
|
|
||||||
error = lock_table_for_trx(child, trx, LOCK_X);
|
|
||||||
if (error != DB_SUCCESS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dict_sys.unfreeze();
|
|
||||||
|
|
||||||
if (ctx->new_table->fts) {
|
if (ctx->new_table->fts) {
|
||||||
ut_ad(!ctx->new_table->fts->add_wq);
|
ut_ad(!ctx->new_table->fts->add_wq);
|
||||||
|
@ -1311,14 +1311,14 @@ class dict_sys_t
|
|||||||
/** The my_hrtime_coarse().val of the oldest lock_wait() start, or 0 */
|
/** The my_hrtime_coarse().val of the oldest lock_wait() start, or 0 */
|
||||||
std::atomic<ulonglong> latch_ex_wait_start;
|
std::atomic<ulonglong> latch_ex_wait_start;
|
||||||
|
|
||||||
/** the rw-latch protecting the data dictionary cache */
|
|
||||||
alignas(CPU_LEVEL1_DCACHE_LINESIZE) srw_lock latch;
|
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
/** whether latch is being held in exclusive mode (by any thread) */
|
typedef index_lock dict_lock;
|
||||||
Atomic_relaxed<pthread_t> latch_ex;
|
#else
|
||||||
/** number of S-latch holders */
|
typedef srw_lock dict_lock;
|
||||||
Atomic_counter<uint32_t> latch_readers;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** the rw-latch protecting the data dictionary cache */
|
||||||
|
alignas(CPU_LEVEL1_DCACHE_LINESIZE) dict_lock latch;
|
||||||
public:
|
public:
|
||||||
/** Indexes of SYS_TABLE[] */
|
/** Indexes of SYS_TABLE[] */
|
||||||
enum
|
enum
|
||||||
@ -1469,15 +1469,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
/** @return whether any thread (not necessarily the current thread)
|
/** @return whether the current thread is holding the latch */
|
||||||
is holding the latch; that is, this check may return false
|
bool frozen() const { return latch.have_any(); }
|
||||||
positives */
|
/** @return whether the current thread is holding a shared latch */
|
||||||
bool frozen() const { return latch_readers || latch_ex; }
|
bool frozen_not_locked() const { return latch.have_s(); }
|
||||||
/** @return whether any thread (not necessarily the current thread)
|
|
||||||
is holding a shared latch */
|
|
||||||
bool frozen_not_locked() const { return latch_readers; }
|
|
||||||
/** @return whether the current thread holds the exclusive latch */
|
/** @return whether the current thread holds the exclusive latch */
|
||||||
bool locked() const { return latch_ex == pthread_self(); }
|
bool locked() const { return latch.have_x(); }
|
||||||
#endif
|
#endif
|
||||||
private:
|
private:
|
||||||
/** Acquire the exclusive latch */
|
/** Acquire the exclusive latch */
|
||||||
@ -1492,13 +1489,11 @@ public:
|
|||||||
/** Exclusively lock the dictionary cache. */
|
/** Exclusively lock the dictionary cache. */
|
||||||
void lock(SRW_LOCK_ARGS(const char *file, unsigned line))
|
void lock(SRW_LOCK_ARGS(const char *file, unsigned line))
|
||||||
{
|
{
|
||||||
if (latch.wr_lock_try())
|
#ifdef UNIV_DEBUG
|
||||||
{
|
if (!latch.x_lock_try())
|
||||||
ut_ad(!latch_readers);
|
#else
|
||||||
ut_ad(!latch_ex);
|
if (!latch.wr_lock_try())
|
||||||
ut_d(latch_ex= pthread_self());
|
#endif
|
||||||
}
|
|
||||||
else
|
|
||||||
lock_wait(SRW_LOCK_ARGS(file, line));
|
lock_wait(SRW_LOCK_ARGS(file, line));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1513,24 +1508,29 @@ public:
|
|||||||
/** Unlock the data dictionary cache. */
|
/** Unlock the data dictionary cache. */
|
||||||
void unlock()
|
void unlock()
|
||||||
{
|
{
|
||||||
ut_ad(latch_ex == pthread_self());
|
# ifdef UNIV_DEBUG
|
||||||
ut_ad(!latch_readers);
|
latch.x_unlock();
|
||||||
ut_d(latch_ex= 0);
|
# else
|
||||||
latch.wr_unlock();
|
latch.wr_unlock();
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
/** Acquire a shared lock on the dictionary cache. */
|
/** Acquire a shared lock on the dictionary cache. */
|
||||||
void freeze()
|
void freeze()
|
||||||
{
|
{
|
||||||
|
# ifdef UNIV_DEBUG
|
||||||
|
latch.s_lock();
|
||||||
|
# else
|
||||||
latch.rd_lock();
|
latch.rd_lock();
|
||||||
ut_ad(!latch_ex);
|
# endif
|
||||||
ut_d(latch_readers++);
|
|
||||||
}
|
}
|
||||||
/** Release a shared lock on the dictionary cache. */
|
/** Release a shared lock on the dictionary cache. */
|
||||||
void unfreeze()
|
void unfreeze()
|
||||||
{
|
{
|
||||||
ut_ad(!latch_ex);
|
# ifdef UNIV_DEBUG
|
||||||
ut_ad(latch_readers--);
|
latch.s_unlock();
|
||||||
|
# else
|
||||||
latch.rd_unlock();
|
latch.rd_unlock();
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -438,6 +438,13 @@ dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode,
|
|||||||
bool no_wait= false)
|
bool no_wait= false)
|
||||||
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||||
|
|
||||||
|
/** Lock the child tables of a table.
|
||||||
|
@param table parent table
|
||||||
|
@param trx transaction
|
||||||
|
@return error code */
|
||||||
|
dberr_t lock_table_children(dict_table_t *table, trx_t *trx)
|
||||||
|
MY_ATTRIBUTE((nonnull, warn_unused_result));
|
||||||
|
|
||||||
/** Exclusively lock the data dictionary tables.
|
/** Exclusively lock the data dictionary tables.
|
||||||
@param trx dictionary transaction
|
@param trx dictionary transaction
|
||||||
@return error code
|
@return error code
|
||||||
|
@ -3940,6 +3940,8 @@ static void lock_table_dequeue(lock_t *in_lock, bool owns_wait_mutex)
|
|||||||
dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode,
|
dberr_t lock_table_for_trx(dict_table_t *table, trx_t *trx, lock_mode mode,
|
||||||
bool no_wait)
|
bool no_wait)
|
||||||
{
|
{
|
||||||
|
ut_ad(!dict_sys.frozen());
|
||||||
|
|
||||||
mem_heap_t *heap= mem_heap_create(512);
|
mem_heap_t *heap= mem_heap_create(512);
|
||||||
sel_node_t *node= sel_node_create(heap);
|
sel_node_t *node= sel_node_create(heap);
|
||||||
que_thr_t *thr= pars_complete_graph_for_exec(node, trx, heap, nullptr);
|
que_thr_t *thr= pars_complete_graph_for_exec(node, trx, heap, nullptr);
|
||||||
@ -3976,6 +3978,36 @@ run_again:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Lock the child tables of a table.
|
||||||
|
@param table parent table
|
||||||
|
@param trx transaction
|
||||||
|
@return error code */
|
||||||
|
dberr_t lock_table_children(dict_table_t *table, trx_t *trx)
|
||||||
|
{
|
||||||
|
dict_sys.freeze(SRW_LOCK_CALL);
|
||||||
|
std::vector<dict_table_t*> children;
|
||||||
|
|
||||||
|
for (auto f : table->referenced_set)
|
||||||
|
if (dict_table_t *child= f->foreign_table)
|
||||||
|
{
|
||||||
|
child->acquire();
|
||||||
|
children.emplace_back(child);
|
||||||
|
}
|
||||||
|
dict_sys.unfreeze();
|
||||||
|
|
||||||
|
dberr_t err= DB_SUCCESS;
|
||||||
|
|
||||||
|
for (auto child : children)
|
||||||
|
if ((err= lock_table_for_trx(child, trx, LOCK_X)) != DB_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (auto child : children)
|
||||||
|
child->release();
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Exclusively lock the data dictionary tables.
|
/** Exclusively lock the data dictionary tables.
|
||||||
@param trx dictionary transaction
|
@param trx dictionary transaction
|
||||||
@return error code
|
@return error code
|
||||||
|
Loading…
x
Reference in New Issue
Block a user