summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/main/events_bugs.result4
-rw-r--r--mysql-test/main/events_bugs.test4
-rw-r--r--mysql-test/main/func_misc.result13
-rw-r--r--mysql-test/main/func_misc.test15
-rw-r--r--mysql-test/main/group_by.result16
-rw-r--r--mysql-test/main/group_by.test14
-rwxr-xr-xmysql-test/mysql-test-run.pl4
-rw-r--r--mysql-test/suite/galera/disabled.def2
-rw-r--r--mysql-test/suite/galera/r/MDEV-20793.result39
-rw-r--r--mysql-test/suite/galera/t/MDEV-20793.test77
-rw-r--r--mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test7
-rw-r--r--sql/item.cc40
-rw-r--r--sql/item.h9
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/wsrep_high_priority_service.cc4
-rw-r--r--storage/innobase/btr/btr0cur.cc27
-rw-r--r--storage/innobase/buf/buf0flu.cc20
m---------wsrep-lib0
18 files changed, 249 insertions, 48 deletions
diff --git a/mysql-test/main/events_bugs.result b/mysql-test/main/events_bugs.result
index cb8850112a5..4870c464fff 100644
--- a/mysql-test/main/events_bugs.result
+++ b/mysql-test/main/events_bugs.result
@@ -692,7 +692,7 @@ SET GLOBAL READ_ONLY = 1;
connect u1_con,localhost,mysqltest_u1,,events_test;
-CREATE EVENT e1 ON SCHEDULE AT '2020-01-01 00:00:00' DO SET @a = 1;
+CREATE EVENT e1 ON SCHEDULE AT '2038-01-01 00:00:00' DO SET @a = 1;
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
ALTER EVENT e1 COMMENT 'comment';
@@ -703,7 +703,7 @@ ERROR HY000: The MariaDB server is running with the --read-only option so it can
connect root_con,localhost,root,,events_test;
-CREATE EVENT e1 ON SCHEDULE AT '2020-01-01 00:00:00' DO SET @a = 1;
+CREATE EVENT e1 ON SCHEDULE AT '2038-01-01 00:00:00' DO SET @a = 1;
Warnings:
Warning 1105 Event scheduler is switched off, use SET GLOBAL event_scheduler=ON to enable it.
diff --git a/mysql-test/main/events_bugs.test b/mysql-test/main/events_bugs.test
index a0f3c5991ef..ab45446667e 100644
--- a/mysql-test/main/events_bugs.test
+++ b/mysql-test/main/events_bugs.test
@@ -1029,7 +1029,7 @@ SET GLOBAL READ_ONLY = 1;
--echo
--error ER_OPTION_PREVENTS_STATEMENT
-CREATE EVENT e1 ON SCHEDULE AT '2020-01-01 00:00:00' DO SET @a = 1;
+CREATE EVENT e1 ON SCHEDULE AT '2038-01-01 00:00:00' DO SET @a = 1;
--echo
@@ -1049,7 +1049,7 @@ DROP EVENT e1;
--echo
-CREATE EVENT e1 ON SCHEDULE AT '2020-01-01 00:00:00' DO SET @a = 1;
+CREATE EVENT e1 ON SCHEDULE AT '2038-01-01 00:00:00' DO SET @a = 1;
--echo
diff --git a/mysql-test/main/func_misc.result b/mysql-test/main/func_misc.result
index 38d3d927416..ae6686ecadc 100644
--- a/mysql-test/main/func_misc.result
+++ b/mysql-test/main/func_misc.result
@@ -1494,6 +1494,19 @@ x
x
DEALLOCATE PREPARE stmt;
#
+# MDEV-19680: Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index) ||
+# (!(ptr >= table->record[0] && ptr < table->record[0] + table->s->reclength)))'
+# or alike failed upon SELECT with mix of functions from simple view
+#
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1),(2);
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT ISNULL( BENCHMARK(1, MIN(a))) FROM v1;
+ISNULL( BENCHMARK(1, MIN(a)))
+0
+DROP VIEW v1;
+DROP TABLE t1;
+#
# Start of 10.2 tests
#
#
diff --git a/mysql-test/main/func_misc.test b/mysql-test/main/func_misc.test
index ea76bce3f6e..7d19c9e58af 100644
--- a/mysql-test/main/func_misc.test
+++ b/mysql-test/main/func_misc.test
@@ -1139,6 +1139,21 @@ PREPARE stmt FROM "SELECT 'x' ORDER BY NAME_CONST( 'f', 'foo' )";
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
+--echo #
+--echo # MDEV-19680: Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index) ||
+--echo # (!(ptr >= table->record[0] && ptr < table->record[0] + table->s->reclength)))'
+--echo # or alike failed upon SELECT with mix of functions from simple view
+--echo #
+
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1),(2);
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+SELECT ISNULL( BENCHMARK(1, MIN(a))) FROM v1;
+
+DROP VIEW v1;
+DROP TABLE t1;
+
--echo #
--echo # Start of 10.2 tests
diff --git a/mysql-test/main/group_by.result b/mysql-test/main/group_by.result
index 3108f2f4e65..47873b09d90 100644
--- a/mysql-test/main/group_by.result
+++ b/mysql-test/main/group_by.result
@@ -2844,6 +2844,22 @@ SELECT 1 IN ( SELECT COUNT( DISTINCT f2 ) FROM t1 WHERE f1 <= 4 );
0
drop table t1;
#
+# MDEV-20922: Adding an order by changes the query results
+#
+CREATE TABLE t1(a int, b int);
+INSERT INTO t1 values (1, 100), (2, 200), (3, 100), (4, 200);
+create view v1 as select a, b+1 as x from t1;
+SELECT x, COUNT(DISTINCT a) AS y FROM v1 GROUP BY x ORDER BY y;
+x y
+101 2
+201 2
+SELECT b+1 AS x, COUNT(DISTINCT a) AS y FROM t1 GROUP BY x ORDER BY y;
+x y
+101 2
+201 2
+drop view v1;
+drop table t1;
+#
# MDEV-10694 - SIGFPE and/or huge memory allocation in maria_create with distinct/group by/ rollup
#
create table t1 (a int,b int) ;
diff --git a/mysql-test/main/group_by.test b/mysql-test/main/group_by.test
index 7ba0945cc72..75335dc3956 100644
--- a/mysql-test/main/group_by.test
+++ b/mysql-test/main/group_by.test
@@ -1955,6 +1955,20 @@ SELECT 1 IN ( SELECT COUNT( DISTINCT f2 ) FROM t1 WHERE f1 <= 4 );
drop table t1;
--echo #
+--echo # MDEV-20922: Adding an order by changes the query results
+--echo #
+
+CREATE TABLE t1(a int, b int);
+INSERT INTO t1 values (1, 100), (2, 200), (3, 100), (4, 200);
+
+create view v1 as select a, b+1 as x from t1;
+
+SELECT x, COUNT(DISTINCT a) AS y FROM v1 GROUP BY x ORDER BY y;
+SELECT b+1 AS x, COUNT(DISTINCT a) AS y FROM t1 GROUP BY x ORDER BY y;
+
+drop view v1;
+drop table t1;
+--echo #
--echo # MDEV-10694 - SIGFPE and/or huge memory allocation in maria_create with distinct/group by/ rollup
--echo #
create table t1 (a int,b int) ;
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index cf7365bbc02..0dcdfc0b64c 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -5573,12 +5573,12 @@ sub server_need_restart {
{
delete $server->{'restart_opts'};
my $use_dynamic_option_switch= 0;
- delete $server->{'restart_opts'};
+ my $restart_opts = delete $server->{'restart_opts'} || [];
if (!$use_dynamic_option_switch)
{
mtr_verbose_restart($server, "running with different options '" .
join(" ", @{$extra_opts}) . "' != '" .
- join(" ", @{$started_opts}) . "'" );
+ join(" ", @{$started_opts}, @{$restart_opts}) . "'" );
return 1;
}
diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def
index 061697a7fd8..f888cb9d789 100644
--- a/mysql-test/suite/galera/disabled.def
+++ b/mysql-test/suite/galera/disabled.def
@@ -13,6 +13,7 @@
GCF-1081 : MDEV-18283 Galera test failure on galera.GCF-1081
MW-286 : MDEV-18464 Killing thread can cause mutex deadlock if done concurrently with Galera/replication victim kill
MW-329 : MDEV-19962 Galera test failure on MW-329
+MW-336 : MDEV-21409: Galera test failure on MW-336
MW-360 : needs rewrite to be MariaDB gtid compatible
MW-388: MDEV-19803 Long semaphore wait error on galera.MW-388
galera_account_management : MariaDB 10.0 does not support ALTER USER
@@ -45,3 +46,4 @@ galera_wan : MDEV-17259 Test failure on galera.galera_wan
mysql-wsrep#198 : MDEV-18935 Galera test mysql-wsrep#198 sporaric assertion transaction.cpp:362: int wsrep::transaction::before_commit(): Assertion `state() == s_executing || state() == s_committing || state() == s_must_abort || state() == s_replaying' failed.
partition : MDEV-19958 Galera test failure on galera.partition
query_cache: MDEV-15805 Test failure on galera.query_cache
+
diff --git a/mysql-test/suite/galera/r/MDEV-20793.result b/mysql-test/suite/galera/r/MDEV-20793.result
new file mode 100644
index 00000000000..b420c8720f5
--- /dev/null
+++ b/mysql-test/suite/galera/r/MDEV-20793.result
@@ -0,0 +1,39 @@
+connection node_2;
+connection node_1;
+CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT);
+INSERT INTO t1 VALUES (1, 0), (5, 0);
+connection node_1_ctrl;
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_slave_threads = 2;
+connection node_1;
+SET SESSION wsrep_retry_autocommit = 0;
+START TRANSACTION;
+UPDATE t1 SET f2 = 1;
+SET SESSION debug_sync = "wsrep_before_replay SIGNAL reached WAIT_FOR continue";
+connection node_1_ctrl;
+SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
+connection node_2;
+INSERT INTO t1 VALUES (2, 2);
+connection node_1_ctrl;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_slave_enter_sync';
+connection node_2;
+UPDATE t1 SET f2 = 2 WHERE f1 = 5;
+connection node_1_ctrl;
+SET SESSION wsrep_on = 0;
+SET SESSION wsrep_on = 1;
+connection node_1;
+COMMIT;
+connection node_1_ctrl;
+SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
+SET SESSION debug_sync = "now WAIT_FOR reached";
+SET GLOBAL wsrep_provider_options = 'signal=local_monitor_slave_enter_sync';
+SET GLOBAL wsrep_provider_options = 'dbug=';
+SET SESSION debug_sync = "now SIGNAL continue";
+connection node_1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SET debug_sync = "RESET";
+DROP TABLE t1;
+SET GLOBAL wsrep_slave_threads = 1;
diff --git a/mysql-test/suite/galera/t/MDEV-20793.test b/mysql-test/suite/galera/t/MDEV-20793.test
new file mode 100644
index 00000000000..9f0fa3e1cb6
--- /dev/null
+++ b/mysql-test/suite/galera/t/MDEV-20793.test
@@ -0,0 +1,77 @@
+#
+# MDEV-20793 Assertion after certification failure during replay.
+#
+# The test outline:
+# In order to produce certification failure three transactions
+# are needed. One transaction is executing on node_1 and two others
+# on node_2. The first transaction from node_2 BF aborts the transaction
+# on node_1, but does not cause certification conflict. The second
+# transaction from node_2 will cause conflict and the transaction on
+# node_1 fails in certification during replay.
+#
+
+--source include/galera_cluster.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+
+CREATE TABLE t1 (f1 INT PRIMARY KEY, f2 INT);
+INSERT INTO t1 VALUES (1, 0), (5, 0);
+
+--let galera_connection_name = node_1_ctrl
+--let galera_server_number = 1
+--source include/galera_connect.inc
+--connection node_1_ctrl
+SET SESSION wsrep_sync_wait = 0;
+SET GLOBAL wsrep_slave_threads = 2;
+
+--connection node_1
+# Start transaction which takes gap lock 1 - 5
+SET SESSION wsrep_retry_autocommit = 0;
+START TRANSACTION;
+UPDATE t1 SET f2 = 1;
+SET SESSION debug_sync = "wsrep_before_replay SIGNAL reached WAIT_FOR continue";
+
+--connection node_1_ctrl
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+--connection node_2
+# Insert into gap from other node. This generates BF abort but does not
+# conflict with update.
+INSERT INTO t1 VALUES (2, 2);
+
+--connection node_1_ctrl
+--source include/galera_wait_sync_point.inc
+--source include/galera_clear_sync_point.inc
+--let $galera_sync_point = local_monitor_slave_enter_sync
+--source include/galera_set_sync_point.inc
+
+# Make an update which will conflict with update on node_1
+--connection node_2
+UPDATE t1 SET f2 = 2 WHERE f1 = 5;
+
+--connection node_1_ctrl
+--let $galera_sync_point = apply_monitor_slave_enter_sync local_monitor_slave_enter_sync
+--source include/galera_wait_sync_point.inc
+
+--connection node_1
+--send COMMIT
+
+--connection node_1_ctrl
+--let $galera_sync_point = apply_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+SET SESSION debug_sync = "now WAIT_FOR reached";
+
+--let $galera_sync_point = local_monitor_slave_enter_sync
+--source include/galera_signal_sync_point.inc
+--source include/galera_clear_sync_point.inc
+SET SESSION debug_sync = "now SIGNAL continue";
+
+--connection node_1
+--error ER_LOCK_DEADLOCK
+--reap
+
+SET debug_sync = "RESET";
+
+DROP TABLE t1;
+SET GLOBAL wsrep_slave_threads = 1;
diff --git a/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test b/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test
index 0730f0380f5..7f3a8e5f693 100644
--- a/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test
+++ b/mysql-test/suite/galera/t/galera_parallel_autoinc_largetrx.test
@@ -37,17 +37,24 @@ SET GLOBAL wsrep_slave_threads = 4;
--connection node_1
--reap
+--let $wait_condition = select count(*)=30000 from t1;
+--source include/wait_condition.inc
+
SELECT COUNT(*) FROM t1;
SELECT COUNT(DISTINCT f1) FROM t1;
--connection node_1a
--reap
+--let $wait_condition = select count(*)=30000 from t1;
+--source include/wait_condition.inc
SELECT COUNT(*) FROM t1;
SELECT COUNT(DISTINCT f1) FROM t1;
--connection node_2
--reap
--disconnect node_1a
+--let $wait_condition = select count(*)=30000 from t1;
+--source include/wait_condition.inc
SELECT COUNT(*) FROM t1;
SELECT COUNT(DISTINCT f1) FROM t1;
diff --git a/sql/item.cc b/sql/item.cc
index 92b127cf773..bb1aa80f642 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9157,6 +9157,46 @@ bool Item_args::excl_dep_on_grouping_fields(st_select_lex *sel)
}
+double Item_direct_view_ref::val_result()
+{
+ double tmp=(*ref)->val_result();
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+longlong Item_direct_view_ref::val_int_result()
+{
+ longlong tmp=(*ref)->val_int_result();
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+String *Item_direct_view_ref::str_result(String* tmp)
+{
+ tmp=(*ref)->str_result(tmp);
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+my_decimal *Item_direct_view_ref::val_decimal_result(my_decimal *val)
+{
+ my_decimal *tmp= (*ref)->val_decimal_result(val);
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
+bool Item_direct_view_ref::val_bool_result()
+{
+ bool tmp= (*ref)->val_bool_result();
+ null_value=(*ref)->null_value;
+ return tmp;
+}
+
+
bool Item_default_value::eq(const Item *item, bool binary_cmp) const
{
return item->type() == DEFAULT_VALUE_ITEM &&
diff --git a/sql/item.h b/sql/item.h
index 880d4ec0d27..c1f68a4f942 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -5764,6 +5764,15 @@ public:
item_equal= NULL;
Item_direct_ref::cleanup();
}
+ /*
+ TODO move these val_*_result function to Item_dierct_ref (maybe)
+ */
+ double val_result();
+ longlong val_int_result();
+ String *str_result(String* tmp);
+ my_decimal *val_decimal_result(my_decimal *val);
+ bool val_bool_result();
+
Item *get_copy(THD *thd)
{ return get_item_copy<Item_direct_view_ref>(thd, this); }
Item *field_transformer_for_having_pushdown(THD *thd, uchar *arg)
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index cf980ac02eb..b3ab9aa7ea7 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -5108,7 +5108,7 @@ void SELECT_LEX::update_used_tables()
}
Item *item;
- List_iterator_fast<Item> it(join->fields_list);
+ List_iterator_fast<Item> it(join->all_fields);
select_list_tables= 0;
while ((item= it++))
{
diff --git a/sql/wsrep_high_priority_service.cc b/sql/wsrep_high_priority_service.cc
index f5847493d10..2bd15a5a77f 100644
--- a/sql/wsrep_high_priority_service.cc
+++ b/sql/wsrep_high_priority_service.cc
@@ -616,9 +616,7 @@ Wsrep_replayer_service::~Wsrep_replayer_service()
THD* replayer_thd= m_thd;
THD* orig_thd= m_orig_thd;
- /* Store replay result/state to original thread wsrep client
- state and switch execution context back to original. */
- orig_thd->wsrep_cs().after_replay(replayer_thd->wsrep_trx());
+ /* Switch execution context back to original. */
wsrep_after_apply(replayer_thd);
wsrep_after_command_ignore_result(replayer_thd);
wsrep_close(replayer_thd);
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index b82c19f1546..47c0465f583 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -3,7 +3,7 @@
Copyright (c) 1994, 2018, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2015, 2019, MariaDB Corporation.
+Copyright (c) 2015, 2020, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -7744,31 +7744,6 @@ btr_store_big_rec_extern_fields(
== FIL_PAGE_PREV + 4);
compile_time_assert(FIL_NULL == 0xffffffff);
mtr.memset(block, FIL_PAGE_PREV, 8, 0xff);
- /* Write a back pointer to the record
- into the otherwise unused area. This
- information could be useful in
- debugging. Later, we might want to
- implement the possibility to relocate
- BLOB pages. Then, we would need to be
- able to adjust the BLOB pointer in the
- record. We do not store the heap
- number of the record, because it can
- change in page_zip_reorganize() or
- btr_page_reorganize(). However, also
- the page number of the record may
- change when B-tree nodes are split or
- merged.
- NOTE: FIL_PAGE_FILE_FLUSH_LSN space is
- used by R-tree index for a Split Sequence
- Number */
- ut_ad(!dict_index_is_spatial(index));
-
- mtr.write<4>(*block, block->frame
- + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
- space_id);
- mtr.write<4>(*block, block->frame
- + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
- rec_page_no);
mtr.memcpy(*block,
FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
page_zip_get_size(page_zip)
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index 3a203566eb1..c51803ea5e6 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2019, MariaDB Corporation.
+Copyright (c) 2013, 2020, MariaDB Corporation.
Copyright (c) 2013, 2014, Fusion-io
This program is free software; you can redistribute it and/or modify it under
@@ -836,15 +836,15 @@ buf_flush_init_for_writing(
memcpy_aligned<4>(page + srv_page_size
- FIL_PAGE_FCRC32_END_LSN,
FIL_PAGE_LSN + 4 + page, 4);
- } else {
- static_assert(FIL_PAGE_END_LSN_OLD_CHKSUM % 8 == 0, "aligned");
- static_assert(FIL_PAGE_LSN % 8 == 0, "aligned");
- memcpy_aligned<8>(page + srv_page_size
- - FIL_PAGE_END_LSN_OLD_CHKSUM,
- FIL_PAGE_LSN + page, 8);
+ return buf_flush_assign_full_crc32_checksum(page);
}
- if (block && !use_full_checksum && srv_page_size == 16384) {
+ static_assert(FIL_PAGE_END_LSN_OLD_CHKSUM % 8 == 0, "aligned");
+ static_assert(FIL_PAGE_LSN % 8 == 0, "aligned");
+ memcpy_aligned<8>(page + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM,
+ FIL_PAGE_LSN + page, 8);
+
+ if (block && srv_page_size == 16384) {
/* The page type could be garbage in old files
created before MySQL 5.5. Such files always
had a page size of 16 kilobytes. */
@@ -908,10 +908,6 @@ buf_flush_init_for_writing(
uint32_t checksum = BUF_NO_CHECKSUM_MAGIC;
- if (use_full_checksum) {
- return buf_flush_assign_full_crc32_checksum(page);
- }
-
switch (srv_checksum_algorithm_t(srv_checksum_algorithm)) {
case SRV_CHECKSUM_ALGORITHM_INNODB:
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
diff --git a/wsrep-lib b/wsrep-lib
-Subproject 90157ed1b0f8b3f0d1eb3d60ac93ce6d8da7ad7
+Subproject 76f7249b8df209a2a3cefd7d4bbf31f6c72812f