mirror of
https://github.com/MariaDB/server.git
synced 2026-04-19 14:55:32 +02:00
Merge 10.5 into 10.6
This commit is contained in:
commit
9c5835e067
23 changed files with 584 additions and 44 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -10,8 +10,11 @@
|
|||
.ninja_*
|
||||
*.mri
|
||||
*.mri.tpl
|
||||
/.cproject
|
||||
/.project
|
||||
.gdb_history
|
||||
.vs/
|
||||
/.settings/
|
||||
errmsg.sys
|
||||
typescript
|
||||
_CPack_Packages
|
||||
|
|
|
|||
|
|
@ -173,6 +173,10 @@ IF(DISABLE_SHARED)
|
|||
SET(WITHOUT_DYNAMIC_PLUGINS 1)
|
||||
ENDIF()
|
||||
OPTION(ENABLED_PROFILING "Enable profiling" ON)
|
||||
OPTION(ENABLED_JSON_WRITER_CONSISTENCY_CHECKS "Enable Json_writer_object / Json_writer_array checking to produce consistent JSON output" OFF)
|
||||
IF(ENABLED_JSON_WRITER_CONSISTENCY_CHECKS)
|
||||
ADD_DEFINITIONS(-DENABLED_JSON_WRITER_CONSISTENCY_CHECKS)
|
||||
ENDIF()
|
||||
OPTION(WITHOUT_SERVER "Build only the client library and clients" OFF)
|
||||
IF(UNIX)
|
||||
OPTION(WITH_VALGRIND "Valgrind instrumentation" OFF)
|
||||
|
|
|
|||
|
|
@ -11,9 +11,7 @@ MACRO(BUNDLE_PCRE2)
|
|||
FOREACH(lib pcre2-posix pcre2-8)
|
||||
ADD_LIBRARY(${lib} STATIC IMPORTED GLOBAL)
|
||||
ADD_DEPENDENCIES(${lib} pcre2)
|
||||
IF(WIN32)
|
||||
# Debug libary name.
|
||||
# Same condition as in pcre2 CMakeLists.txt that adds "d"
|
||||
|
||||
GET_PROPERTY(MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
IF(MULTICONFIG)
|
||||
SET(intdir "${CMAKE_CFG_INTDIR}/")
|
||||
|
|
@ -22,10 +20,13 @@ MACRO(BUNDLE_PCRE2)
|
|||
ENDIF()
|
||||
|
||||
SET(file ${dir}/src/pcre2-build/${intdir}${CMAKE_STATIC_LIBRARY_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
|
||||
IF(WIN32)
|
||||
# Debug libary name.
|
||||
# Same condition as in pcre2 CMakeLists.txt that adds "d"
|
||||
SET(file_d ${dir}/src/pcre2-build/${intdir}${CMAKE_STATIC_LIBRARY_PREFIX}${lib}d${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
SET_TARGET_PROPERTIES(${lib} PROPERTIES IMPORTED_LOCATION_DEBUG ${file_d})
|
||||
ELSE()
|
||||
SET(file ${dir}/src/pcre2-build/${CMAKE_STATIC_LIBRARY_PREFIX}${lib}${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
SET(file_d)
|
||||
ENDIF()
|
||||
SET(byproducts ${byproducts} BUILD_BYPRODUCTS ${file} ${file_d})
|
||||
|
|
|
|||
|
|
@ -1271,6 +1271,7 @@ sub command_line_setup {
|
|||
{
|
||||
$path_client_bindir= mtr_path_exists("$bindir/client_release",
|
||||
"$bindir/client_debug",
|
||||
"$bindir/client/debug",
|
||||
"$bindir/client$opt_vs_config",
|
||||
"$bindir/client",
|
||||
"$bindir/bin");
|
||||
|
|
|
|||
|
|
@ -71,35 +71,16 @@ connection node_3a;
|
|||
SET SESSION wsrep_sync_wait = 0;
|
||||
SET SESSION wsrep_sync_wait = DEFAULT;
|
||||
connection node_1a;
|
||||
Timeout in wait_condition.inc for SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log
|
||||
Id User Host db Command Time State Info Progress
|
||||
1 system user NULL Sleep 66 wsrep aborter idle NULL 0.000
|
||||
2 system user NULL Sleep 66 closing tables NULL 0.000
|
||||
10 root localhost test Sleep 58 NULL 0.000
|
||||
11 root localhost:52722 test Sleep 56 NULL 0.000
|
||||
12 root localhost:52724 test Query 0 starting show full processlist 0.000
|
||||
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
|
||||
EXPECT_0
|
||||
1
|
||||
0
|
||||
connection node_2a;
|
||||
Timeout in wait_condition.inc for SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log
|
||||
Id User Host db Command Time State Info Progress
|
||||
1 system user NULL Sleep 96 wsrep aborter idle NULL 0.000
|
||||
2 system user NULL Sleep 87 closing tables NULL 0.000
|
||||
10 root localhost:37222 test Sleep 64 NULL 0.000
|
||||
11 root localhost:37228 test Query 0 starting show full processlist 0.000
|
||||
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
|
||||
EXPECT_0
|
||||
1
|
||||
0
|
||||
connection node_3a;
|
||||
Timeout in wait_condition.inc for SELECT COUNT(*) = 0 FROM mysql.wsrep_streaming_log
|
||||
Id User Host db Command Time State Info Progress
|
||||
1 system user NULL Sleep 122 wsrep aborter idle NULL 0.000
|
||||
2 system user NULL Sleep 117 closing tables NULL 0.000
|
||||
10 root localhost:60992 test Sleep 117 NULL 0.000
|
||||
11 root localhost:60994 test Query 0 starting show full processlist 0.000
|
||||
SELECT COUNT(*) AS EXPECT_0 FROM mysql.wsrep_streaming_log;
|
||||
EXPECT_0
|
||||
1
|
||||
0
|
||||
connection node_1;
|
||||
DROP TABLE t1;
|
||||
|
|
|
|||
|
|
@ -219,4 +219,65 @@ include/sync_with_master_gtid.inc
|
|||
connection master;
|
||||
drop database test_ign;
|
||||
drop table t1, t2, t3, tm;
|
||||
#
|
||||
# MDEV-26682 slave lock timeout with XA and gap locks
|
||||
#
|
||||
create table t1 (a int primary key, b int unique) engine=innodb;
|
||||
insert t1 values (1,1),(3,3),(5,5);
|
||||
connection slave;
|
||||
set session tx_isolation='repeatable-read';
|
||||
start transaction;
|
||||
select * from t1;
|
||||
a b
|
||||
1 1
|
||||
3 3
|
||||
5 5
|
||||
connect m2, localhost, root;
|
||||
delete from t1 where a=3;
|
||||
xa start 'x1';
|
||||
update t1 set b=3 where a=5;
|
||||
xa end 'x1';
|
||||
xa prepare 'x1';
|
||||
connect m3, localhost, root;
|
||||
insert t1 values (2, 2);
|
||||
-->slave
|
||||
connection slave;
|
||||
commit;
|
||||
select * from t1;
|
||||
a b
|
||||
1 1
|
||||
2 2
|
||||
5 5
|
||||
connection m2;
|
||||
xa rollback 'x1';
|
||||
disconnect m2;
|
||||
disconnect m3;
|
||||
connection master;
|
||||
drop table t1;
|
||||
create table t1 (id int auto_increment primary key, c1 int not null unique)
|
||||
engine=innodb;
|
||||
create table t2 (id int auto_increment primary key, c1 int not null,
|
||||
foreign key(c1) references t1(c1), unique key(c1)) engine=innodb;
|
||||
insert t1 values (869,1), (871,3), (873,4), (872,5), (870,6), (877,7);
|
||||
insert t2 values (795,6), (800,7);
|
||||
xa start '1';
|
||||
update t2 set id = 9, c1 = 5 where c1 in (null, null, null, null, null, 7, 3);
|
||||
connect con1, localhost,root;
|
||||
xa start '2';
|
||||
delete from t1 where c1 like '3%';
|
||||
xa end '2';
|
||||
xa prepare '2';
|
||||
connection master;
|
||||
xa end '1';
|
||||
xa prepare '1';
|
||||
->slave
|
||||
connection slave;
|
||||
connection slave;
|
||||
include/sync_with_master_gtid.inc
|
||||
connection con1;
|
||||
xa commit '2';
|
||||
disconnect con1;
|
||||
connection master;
|
||||
xa commit '1';
|
||||
drop table t2, t1;
|
||||
include/rpl_end.inc
|
||||
|
|
|
|||
|
|
@ -228,6 +228,67 @@ include/sync_with_master_gtid.inc
|
|||
connection master;
|
||||
drop database test_ign;
|
||||
drop table t1, t2, t3, tm;
|
||||
#
|
||||
# MDEV-26682 slave lock timeout with XA and gap locks
|
||||
#
|
||||
create table t1 (a int primary key, b int unique) engine=innodb;
|
||||
insert t1 values (1,1),(3,3),(5,5);
|
||||
connection slave;
|
||||
set session tx_isolation='repeatable-read';
|
||||
start transaction;
|
||||
select * from t1;
|
||||
a b
|
||||
1 1
|
||||
3 3
|
||||
5 5
|
||||
connect m2, localhost, root;
|
||||
delete from t1 where a=3;
|
||||
xa start 'x1';
|
||||
update t1 set b=3 where a=5;
|
||||
xa end 'x1';
|
||||
xa prepare 'x1';
|
||||
connect m3, localhost, root;
|
||||
insert t1 values (2, 2);
|
||||
-->slave
|
||||
connection slave;
|
||||
commit;
|
||||
select * from t1;
|
||||
a b
|
||||
1 1
|
||||
2 2
|
||||
5 5
|
||||
connection m2;
|
||||
xa rollback 'x1';
|
||||
disconnect m2;
|
||||
disconnect m3;
|
||||
connection master;
|
||||
drop table t1;
|
||||
create table t1 (id int auto_increment primary key, c1 int not null unique)
|
||||
engine=innodb;
|
||||
create table t2 (id int auto_increment primary key, c1 int not null,
|
||||
foreign key(c1) references t1(c1), unique key(c1)) engine=innodb;
|
||||
insert t1 values (869,1), (871,3), (873,4), (872,5), (870,6), (877,7);
|
||||
insert t2 values (795,6), (800,7);
|
||||
xa start '1';
|
||||
update t2 set id = 9, c1 = 5 where c1 in (null, null, null, null, null, 7, 3);
|
||||
connect con1, localhost,root;
|
||||
xa start '2';
|
||||
delete from t1 where c1 like '3%';
|
||||
xa end '2';
|
||||
xa prepare '2';
|
||||
connection master;
|
||||
xa end '1';
|
||||
xa prepare '1';
|
||||
->slave
|
||||
connection slave;
|
||||
connection slave;
|
||||
include/sync_with_master_gtid.inc
|
||||
connection con1;
|
||||
xa commit '2';
|
||||
disconnect con1;
|
||||
connection master;
|
||||
xa commit '1';
|
||||
drop table t2, t1;
|
||||
connection slave;
|
||||
include/stop_slave.inc
|
||||
SET @@global.gtid_pos_auto_engines="";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#
|
||||
# This "body" file checks general properties of XA transaction replication
|
||||
# as of MDEV-7974.
|
||||
# as of MDEV-742.
|
||||
# Parameters:
|
||||
# --let rpl_xa_check= SELECT ...
|
||||
#
|
||||
|
|
@ -353,3 +353,81 @@ source include/sync_with_master_gtid.inc;
|
|||
connection master;
|
||||
--eval drop database test_ign
|
||||
drop table t1, t2, t3, tm;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-26682 slave lock timeout with XA and gap locks
|
||||
--echo #
|
||||
create table t1 (a int primary key, b int unique) engine=innodb;
|
||||
insert t1 values (1,1),(3,3),(5,5);
|
||||
sync_slave_with_master;
|
||||
|
||||
# set a strong isolation level to keep the read view below.
|
||||
# alternatively a long-running select can do that too even in read-committed
|
||||
set session tx_isolation='repeatable-read';
|
||||
start transaction;
|
||||
# opens a read view to disable purge on the slave
|
||||
select * from t1;
|
||||
|
||||
connect m2, localhost, root;
|
||||
# now, delete a value, purge it on the master, but not on the slave
|
||||
delete from t1 where a=3;
|
||||
xa start 'x1';
|
||||
# this sets a gap lock on <3>, when it exists (so, on the slave)
|
||||
update t1 set b=3 where a=5;
|
||||
xa end 'x1';
|
||||
xa prepare 'x1';
|
||||
|
||||
connect m3, localhost, root;
|
||||
# and this tries to insert straight into the locked gap
|
||||
insert t1 values (2, 2);
|
||||
|
||||
echo -->slave;
|
||||
sync_slave_with_master;
|
||||
commit;
|
||||
select * from t1;
|
||||
|
||||
connection m2;
|
||||
xa rollback 'x1';
|
||||
disconnect m2;
|
||||
disconnect m3;
|
||||
|
||||
connection master;
|
||||
|
||||
drop table t1;
|
||||
|
||||
create table t1 (id int auto_increment primary key, c1 int not null unique)
|
||||
engine=innodb;
|
||||
|
||||
create table t2 (id int auto_increment primary key, c1 int not null,
|
||||
foreign key(c1) references t1(c1), unique key(c1)) engine=innodb;
|
||||
|
||||
insert t1 values (869,1), (871,3), (873,4), (872,5), (870,6), (877,7);
|
||||
insert t2 values (795,6), (800,7);
|
||||
|
||||
xa start '1';
|
||||
update t2 set id = 9, c1 = 5 where c1 in (null, null, null, null, null, 7, 3);
|
||||
|
||||
connect con1, localhost,root;
|
||||
xa start '2';
|
||||
delete from t1 where c1 like '3%';
|
||||
xa end '2';
|
||||
xa prepare '2';
|
||||
|
||||
connection master;
|
||||
xa end '1';
|
||||
xa prepare '1';
|
||||
|
||||
echo ->slave;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
connection slave;
|
||||
source include/sync_with_master_gtid.inc;
|
||||
|
||||
connection con1;
|
||||
xa commit '2';
|
||||
disconnect con1;
|
||||
|
||||
connection master;
|
||||
xa commit '1';
|
||||
drop table t2, t1;
|
||||
|
|
|
|||
|
|
@ -88,5 +88,32 @@ Warnings:
|
|||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::ff'
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle<NATIVE_LEN, MAX_CHAR_LEN>::Type_handler_fbt::stored_field_cmp_to_item
|
||||
#
|
||||
CREATE TABLE t1 (pk inet6, c text) engine=myisam;
|
||||
INSERT INTO t1 VALUES ('::',1);
|
||||
CREATE TABLE t2 (d text, KEY (d)) engine=innodb ;
|
||||
Warnings:
|
||||
Note 1071 Specified key was too long; max key length is 3072 bytes
|
||||
INSERT INTO t2 VALUES (2);
|
||||
SELECT * FROM t2 JOIN t1 ON ( t1.pk > t2.d);
|
||||
d pk c
|
||||
Warnings:
|
||||
Warning 1292 Incorrect inet6 value: '2'
|
||||
UPDATE t2 JOIN t1 ON ( t1.pk > t2.d) SET t1.c = 1;
|
||||
ERROR 22007: Incorrect inet6 value: '2'
|
||||
SET sql_mode='';
|
||||
UPDATE t2 JOIN t1 ON ( t1.pk > t2.d) SET t1.c = 1;
|
||||
Warnings:
|
||||
Warning 1292 Incorrect inet6 value: '2'
|
||||
SET sql_mode=DEFAULT;
|
||||
SELECT * FROM t1;
|
||||
pk c
|
||||
:: 1
|
||||
SELECT * FROM t2;
|
||||
d
|
||||
2
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
|
|
|
|||
|
|
@ -12,6 +12,24 @@
|
|||
SET default_storage_engine=InnoDB;
|
||||
--source type_inet6_engines.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle<NATIVE_LEN, MAX_CHAR_LEN>::Type_handler_fbt::stored_field_cmp_to_item
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (pk inet6, c text) engine=myisam;
|
||||
INSERT INTO t1 VALUES ('::',1);
|
||||
CREATE TABLE t2 (d text, KEY (d)) engine=innodb ;
|
||||
INSERT INTO t2 VALUES (2);
|
||||
SELECT * FROM t2 JOIN t1 ON ( t1.pk > t2.d);
|
||||
--error ER_TRUNCATED_WRONG_VALUE
|
||||
UPDATE t2 JOIN t1 ON ( t1.pk > t2.d) SET t1.c = 1;
|
||||
SET sql_mode='';
|
||||
UPDATE t2 JOIN t1 ON ( t1.pk > t2.d) SET t1.c = 1;
|
||||
SET sql_mode=DEFAULT;
|
||||
SELECT * FROM t1;
|
||||
SELECT * FROM t2;
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
|
|
|
|||
|
|
@ -88,5 +88,24 @@ Warnings:
|
|||
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = INET6'::ff'
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle<NATIVE_LEN, MAX_CHAR_LEN>::Type_handler_fbt::stored_field_cmp_to_item
|
||||
#
|
||||
CREATE TABLE t1 (c varchar(64), key(c)) engine=myisam;
|
||||
INSERT INTO t1 VALUES ('0::1'),('::1'),('::2');
|
||||
SELECT * FROM t1 WHERE c>CAST('::1' AS INET6);
|
||||
c
|
||||
::2
|
||||
EXPLAIN SELECT * FROM t1 WHERE c>CAST('::1' AS INET6);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index c c 67 NULL 3 Using where; Using index
|
||||
SELECT * FROM t1 WHERE c=CAST('::1' AS INET6);
|
||||
c
|
||||
0::1
|
||||
::1
|
||||
EXPLAIN SELECT * FROM t1 WHERE c=CAST('::1' AS INET6);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index c c 67 NULL 3 Using where; Using index
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.5 tests
|
||||
#
|
||||
|
|
|
|||
|
|
@ -10,6 +10,18 @@
|
|||
SET default_storage_engine=MyISAM;
|
||||
--source type_inet6_engines.inc
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-26742 Assertion `field->type_handler() == this' failed in FixedBinTypeBundle<NATIVE_LEN, MAX_CHAR_LEN>::Type_handler_fbt::stored_field_cmp_to_item
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (c varchar(64), key(c)) engine=myisam;
|
||||
INSERT INTO t1 VALUES ('0::1'),('::1'),('::2');
|
||||
SELECT * FROM t1 WHERE c>CAST('::1' AS INET6);
|
||||
EXPLAIN SELECT * FROM t1 WHERE c>CAST('::1' AS INET6);
|
||||
SELECT * FROM t1 WHERE c=CAST('::1' AS INET6);
|
||||
EXPLAIN SELECT * FROM t1 WHERE c=CAST('::1' AS INET6);
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.5 tests
|
||||
|
|
|
|||
19
sql/field.cc
19
sql/field.cc
|
|
@ -1276,6 +1276,21 @@ bool Field::can_be_substituted_to_equal_item(const Context &ctx,
|
|||
}
|
||||
|
||||
|
||||
bool Field::cmp_is_done_using_type_handler_of_this(const Item_bool_func *cond,
|
||||
const Item *item) const
|
||||
{
|
||||
/*
|
||||
We could eventually take comparison_type_handler() from cond,
|
||||
instead of calculating it again. But only some descendants of
|
||||
Item_bool_func has this method. So this needs some hierarchy changes.
|
||||
Another option is to pass "class Context" to this method.
|
||||
*/
|
||||
Type_handler_hybrid_field_type cmp(type_handler_for_comparison());
|
||||
return !cmp.aggregate_for_comparison(item->type_handler_for_comparison()) &&
|
||||
cmp.type_handler() == type_handler_for_comparison();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This handles all numeric and BIT data types.
|
||||
*/
|
||||
|
|
@ -7368,7 +7383,7 @@ bool
|
|||
Field_longstr::cmp_to_string_with_same_collation(const Item_bool_func *cond,
|
||||
const Item *item) const
|
||||
{
|
||||
return item->cmp_type() == STRING_RESULT &&
|
||||
return cmp_is_done_using_type_handler_of_this(cond, item) &&
|
||||
charset() == cond->compare_collation();
|
||||
}
|
||||
|
||||
|
|
@ -7377,7 +7392,7 @@ bool
|
|||
Field_longstr::cmp_to_string_with_stricter_collation(const Item_bool_func *cond,
|
||||
const Item *item) const
|
||||
{
|
||||
return item->cmp_type() == STRING_RESULT &&
|
||||
return cmp_is_done_using_type_handler_of_this(cond, item) &&
|
||||
(charset() == cond->compare_collation() ||
|
||||
cond->compare_collation()->state & MY_CS_BINSORT);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1651,6 +1651,8 @@ protected:
|
|||
}
|
||||
int warn_if_overflow(int op_result);
|
||||
Copy_func *get_identical_copy_func() const;
|
||||
bool cmp_is_done_using_type_handler_of_this(const Item_bool_func *cond,
|
||||
const Item *item) const;
|
||||
bool can_optimize_scalar_range(const RANGE_OPT_PARAM *param,
|
||||
const KEY_PART *key_part,
|
||||
const Item_bool_func *cond,
|
||||
|
|
|
|||
|
|
@ -260,6 +260,10 @@ void Json_writer::add_str(const String &str)
|
|||
add_str(str.ptr(), str.length());
|
||||
}
|
||||
|
||||
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
|
||||
thread_local std::vector<bool> Json_writer_struct::named_items_expectation;
|
||||
#endif
|
||||
|
||||
Json_writer_temp_disable::Json_writer_temp_disable(THD *thd_arg)
|
||||
{
|
||||
thd= thd_arg;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,12 @@
|
|||
|
||||
#ifndef JSON_WRITER_INCLUDED
|
||||
#define JSON_WRITER_INCLUDED
|
||||
|
||||
#include "my_base.h"
|
||||
#include "sql_select.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Opt_trace_stmt;
|
||||
class Opt_trace_context;
|
||||
class Json_writer;
|
||||
|
|
@ -308,6 +312,9 @@ public:
|
|||
/* A common base for Json_writer_object and Json_writer_array */
|
||||
class Json_writer_struct
|
||||
{
|
||||
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
|
||||
static thread_local std::vector<bool> named_items_expectation;
|
||||
#endif
|
||||
protected:
|
||||
Json_writer* my_writer;
|
||||
Json_value_helper context;
|
||||
|
|
@ -317,16 +324,35 @@ protected:
|
|||
bool closed;
|
||||
|
||||
public:
|
||||
explicit Json_writer_struct(THD *thd)
|
||||
explicit Json_writer_struct(THD *thd, bool expect_named_children)
|
||||
{
|
||||
my_writer= thd->opt_trace.get_current_json();
|
||||
context.init(my_writer);
|
||||
closed= false;
|
||||
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
|
||||
named_items_expectation.push_back(expect_named_children);
|
||||
#endif
|
||||
}
|
||||
bool trace_started()
|
||||
|
||||
virtual ~Json_writer_struct()
|
||||
{
|
||||
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
|
||||
named_items_expectation.pop_back();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool trace_started() const
|
||||
{
|
||||
return my_writer != 0;
|
||||
}
|
||||
|
||||
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
|
||||
bool named_item_expected() const
|
||||
{
|
||||
return named_items_expectation.size() > 1
|
||||
&& *(named_items_expectation.rbegin() + 1);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -347,15 +373,21 @@ private:
|
|||
}
|
||||
public:
|
||||
explicit Json_writer_object(THD *thd)
|
||||
: Json_writer_struct(thd)
|
||||
: Json_writer_struct(thd, true)
|
||||
{
|
||||
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
|
||||
DBUG_ASSERT(!named_item_expected());
|
||||
#endif
|
||||
if (unlikely(my_writer))
|
||||
my_writer->start_object();
|
||||
}
|
||||
|
||||
explicit Json_writer_object(THD* thd, const char *str)
|
||||
: Json_writer_struct(thd)
|
||||
: Json_writer_struct(thd, true)
|
||||
{
|
||||
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
|
||||
DBUG_ASSERT(named_item_expected());
|
||||
#endif
|
||||
if (unlikely(my_writer))
|
||||
my_writer->add_member(str).start_object();
|
||||
}
|
||||
|
|
@ -519,14 +551,22 @@ public:
|
|||
class Json_writer_array : public Json_writer_struct
|
||||
{
|
||||
public:
|
||||
Json_writer_array(THD *thd): Json_writer_struct(thd)
|
||||
Json_writer_array(THD *thd)
|
||||
: Json_writer_struct(thd, false)
|
||||
{
|
||||
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
|
||||
DBUG_ASSERT(!named_item_expected());
|
||||
#endif
|
||||
if (unlikely(my_writer))
|
||||
my_writer->start_array();
|
||||
}
|
||||
|
||||
Json_writer_array(THD *thd, const char *str) : Json_writer_struct(thd)
|
||||
Json_writer_array(THD *thd, const char *str)
|
||||
: Json_writer_struct(thd, false)
|
||||
{
|
||||
#ifdef ENABLED_JSON_WRITER_CONSISTENCY_CHECKS
|
||||
DBUG_ASSERT(named_item_expected());
|
||||
#endif
|
||||
if (unlikely(my_writer))
|
||||
my_writer->add_member(str).start_array();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -427,6 +427,10 @@ lock_rec_unlock(
|
|||
and release possible other transactions waiting because of these locks. */
|
||||
void lock_release(trx_t* trx);
|
||||
|
||||
/** Release non-exclusive locks on XA PREPARE,
|
||||
and release possible other transactions waiting because of these locks. */
|
||||
void lock_release_on_prepare(trx_t *trx);
|
||||
|
||||
/** Release locks on a table whose creation is being rolled back */
|
||||
ATTRIBUTE_COLD void lock_release_on_rollback(trx_t *trx, dict_table_t *table);
|
||||
|
||||
|
|
|
|||
|
|
@ -3883,6 +3883,124 @@ released:
|
|||
#endif
|
||||
}
|
||||
|
||||
/** Release non-exclusive locks on XA PREPARE,
|
||||
and wake up possible other transactions waiting because of these locks.
|
||||
@param trx transaction in XA PREPARE state
|
||||
@return whether all locks were released */
|
||||
static bool lock_release_on_prepare_try(trx_t *trx)
|
||||
{
|
||||
/* At this point, trx->lock.trx_locks can still be modified by other
|
||||
threads to convert implicit exclusive locks into explicit ones.
|
||||
|
||||
The function lock_table_create() should never be invoked on behalf
|
||||
of a transaction that is running in another thread. Also there, we
|
||||
will assert that the current transaction be active. */
|
||||
DBUG_ASSERT(trx->state == TRX_STATE_PREPARED);
|
||||
|
||||
bool all_released= true;
|
||||
lock_sys.rd_lock(SRW_LOCK_CALL);
|
||||
trx->mutex_lock();
|
||||
|
||||
/* Note: Normally, trx->mutex is not held while acquiring
|
||||
a lock table latch, but here we are following the opposite order.
|
||||
To avoid deadlocks, we only try to acquire the lock table latches
|
||||
but not keep waiting for them. */
|
||||
|
||||
for (lock_t *prev, *lock= UT_LIST_GET_LAST(trx->lock.trx_locks); lock;
|
||||
lock= prev)
|
||||
{
|
||||
ut_ad(lock->trx == trx);
|
||||
prev= UT_LIST_GET_PREV(trx_locks, lock);
|
||||
if (!lock->is_table())
|
||||
{
|
||||
ut_ad(!lock->index->table->is_temporary());
|
||||
if (lock->mode() == LOCK_X && !lock->is_gap())
|
||||
continue;
|
||||
auto &lock_hash= lock_sys.hash_get(lock->type_mode);
|
||||
auto cell= lock_hash.cell_get(lock->un_member.rec_lock.page_id.fold());
|
||||
auto latch= lock_sys_t::hash_table::latch(cell);
|
||||
if (latch->try_acquire())
|
||||
{
|
||||
lock_rec_dequeue_from_page(lock, false);
|
||||
latch->release();
|
||||
}
|
||||
else
|
||||
all_released= false;
|
||||
}
|
||||
else
|
||||
{
|
||||
dict_table_t *table= lock->un_member.tab_lock.table;
|
||||
ut_ad(!table->is_temporary());
|
||||
switch (lock->mode()) {
|
||||
case LOCK_IS:
|
||||
case LOCK_S:
|
||||
if (table->lock_mutex_trylock())
|
||||
{
|
||||
lock_table_dequeue(lock, false);
|
||||
table->lock_mutex_unlock();
|
||||
}
|
||||
else
|
||||
all_released= false;
|
||||
break;
|
||||
case LOCK_IX:
|
||||
case LOCK_X:
|
||||
ut_ad(table->id >= DICT_HDR_FIRST_ID || trx->dict_operation);
|
||||
/* fall through */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lock_sys.rd_unlock();
|
||||
trx->mutex_unlock();
|
||||
return all_released;
|
||||
}
|
||||
|
||||
/** Release non-exclusive locks on XA PREPARE,
|
||||
and release possible other transactions waiting because of these locks. */
|
||||
void lock_release_on_prepare(trx_t *trx)
|
||||
{
|
||||
for (ulint count= 5; count--; )
|
||||
if (lock_release_on_prepare_try(trx))
|
||||
return;
|
||||
|
||||
LockMutexGuard g{SRW_LOCK_CALL};
|
||||
trx->mutex_lock();
|
||||
|
||||
for (lock_t *prev, *lock= UT_LIST_GET_LAST(trx->lock.trx_locks); lock;
|
||||
lock= prev)
|
||||
{
|
||||
ut_ad(lock->trx == trx);
|
||||
prev= UT_LIST_GET_PREV(trx_locks, lock);
|
||||
if (!lock->is_table())
|
||||
{
|
||||
ut_ad(!lock->index->table->is_temporary());
|
||||
if (lock->mode() != LOCK_X || lock->is_gap())
|
||||
lock_rec_dequeue_from_page(lock, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
dict_table_t *table= lock->un_member.tab_lock.table;
|
||||
ut_ad(!table->is_temporary());
|
||||
switch (lock->mode()) {
|
||||
case LOCK_IS:
|
||||
case LOCK_S:
|
||||
lock_table_dequeue(lock, false);
|
||||
break;
|
||||
case LOCK_IX:
|
||||
case LOCK_X:
|
||||
ut_ad(table->id >= DICT_HDR_FIRST_ID || trx->dict_operation);
|
||||
/* fall through */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trx->mutex_unlock();
|
||||
}
|
||||
|
||||
/** Release locks on a table whose creation is being rolled back */
|
||||
ATTRIBUTE_COLD void lock_release_on_rollback(trx_t *trx, dict_table_t *table)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1868,6 +1868,20 @@ trx_prepare(
|
|||
We must not be holding any mutexes or latches here. */
|
||||
|
||||
trx_flush_log_if_needed(lsn, trx);
|
||||
|
||||
if (!UT_LIST_GET_LEN(trx->lock.trx_locks)
|
||||
|| trx->isolation_level == TRX_ISO_SERIALIZABLE) {
|
||||
/* Do not release any locks at the
|
||||
SERIALIZABLE isolation level. */
|
||||
} else if (!trx->mysql_thd
|
||||
|| thd_sql_command(trx->mysql_thd)
|
||||
!= SQLCOM_XA_PREPARE) {
|
||||
/* Do not release locks for XA COMMIT ONE PHASE
|
||||
or for internal distributed transactions
|
||||
(XID::get_my_xid() would be nonzero). */
|
||||
} else {
|
||||
lock_release_on_prepare(trx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
36
storage/spider/mysql-test/spider/bugfix/r/mdev_26539.result
Normal file
36
storage/spider/mysql-test/spider/bugfix/r/mdev_26539.result
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
for master_1
|
||||
for child2
|
||||
child2_1
|
||||
child2_2
|
||||
child2_3
|
||||
for child3
|
||||
#
|
||||
# MDEV-26539 SIGSEGV in spider_check_and_set_trx_isolation and I_P_List_iterator from THD::drop_temporary_table (10.5.3 opt only) on ALTER
|
||||
#
|
||||
connection child2_1;
|
||||
CREATE DATABASE auto_test_remote;
|
||||
USE auto_test_remote;
|
||||
CREATE TABLE tbl_a (
|
||||
c INT
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
connection master_1;
|
||||
CREATE DATABASE auto_test_local;
|
||||
USE auto_test_local;
|
||||
CREATE TABLE tbl_a (
|
||||
c INT
|
||||
) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='table "tbl_a"' PARTITION BY LIST COLUMNS (c) (
|
||||
PARTITION pt1 DEFAULT COMMENT = 'srv "s_2_1"'
|
||||
);
|
||||
INSERT INTO tbl_a VALUES (1);
|
||||
ALTER TABLE tbl_a CHECK PARTITION ALL;
|
||||
Table Op Msg_type Msg_text
|
||||
auto_test_local.tbl_a check status OK
|
||||
DROP DATABASE auto_test_local;
|
||||
connection child2_1;
|
||||
DROP DATABASE auto_test_remote;
|
||||
for master_1
|
||||
for child2
|
||||
child2_1
|
||||
child2_2
|
||||
child2_3
|
||||
for child3
|
||||
3
storage/spider/mysql-test/spider/bugfix/t/mdev_26539.cnf
Normal file
3
storage/spider/mysql-test/spider/bugfix/t/mdev_26539.cnf
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
!include include/default_mysqld.cnf
|
||||
!include ../my_1_1.cnf
|
||||
!include ../my_2_1.cnf
|
||||
40
storage/spider/mysql-test/spider/bugfix/t/mdev_26539.test
Normal file
40
storage/spider/mysql-test/spider/bugfix/t/mdev_26539.test
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
--disable_query_log
|
||||
--disable_result_log
|
||||
--source ../../t/test_init.inc
|
||||
--enable_result_log
|
||||
--enable_query_log
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-26539 SIGSEGV in spider_check_and_set_trx_isolation and I_P_List_iterator from THD::drop_temporary_table (10.5.3 opt only) on ALTER
|
||||
--echo #
|
||||
|
||||
--connection child2_1
|
||||
CREATE DATABASE auto_test_remote;
|
||||
USE auto_test_remote;
|
||||
eval CREATE TABLE tbl_a (
|
||||
c INT
|
||||
) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
|
||||
|
||||
--connection master_1
|
||||
CREATE DATABASE auto_test_local;
|
||||
USE auto_test_local;
|
||||
|
||||
eval CREATE TABLE tbl_a (
|
||||
c INT
|
||||
) $MASTER_1_ENGINE $MASTER_1_CHARSET COMMENT='table "tbl_a"' PARTITION BY LIST COLUMNS (c) (
|
||||
PARTITION pt1 DEFAULT COMMENT = 'srv "s_2_1"'
|
||||
);
|
||||
|
||||
INSERT INTO tbl_a VALUES (1);
|
||||
ALTER TABLE tbl_a CHECK PARTITION ALL;
|
||||
|
||||
DROP DATABASE auto_test_local;
|
||||
|
||||
--connection child2_1
|
||||
DROP DATABASE auto_test_remote;
|
||||
|
||||
--disable_query_log
|
||||
--disable_result_log
|
||||
--source ../../t/test_deinit.inc
|
||||
--enable_result_log
|
||||
--enable_query_log
|
||||
|
|
@ -3802,10 +3802,8 @@ int spider_check_trx_and_get_conn(
|
|||
}
|
||||
spider->wide_handler->trx = trx;
|
||||
spider->set_error_mode();
|
||||
if (
|
||||
spider->wide_handler->sql_command != SQLCOM_DROP_TABLE &&
|
||||
spider->wide_handler->sql_command != SQLCOM_ALTER_TABLE
|
||||
) {
|
||||
if (spider->wide_handler->sql_command != SQLCOM_DROP_TABLE)
|
||||
{
|
||||
SPIDER_TRX_HA *trx_ha = spider_check_trx_ha(trx, spider);
|
||||
if (!trx_ha || trx_ha->wait_for_reusing)
|
||||
spider_trx_set_link_idx_for_all(spider);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue