diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2023-04-21 16:38:22 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2023-04-21 16:38:22 +0300 |
commit | abe4c7bfd6d56dc0557d15eaa03185ada4149da7 (patch) | |
tree | a44ab54d96b7dd988fd87793af53522bee270d43 | |
parent | 7e31a8e7fa97a87fc164381588d172bf0e76abb6 (diff) | |
parent | c6e58a8d173b7e9689952d07678ba79702ba8021 (diff) | |
download | mariadb-git-abe4c7bfd6d56dc0557d15eaa03185ada4149da7.tar.gz |
Merge 10.5 into 10.6
-rw-r--r-- | mysql-test/main/group_min_max.result | 12 | ||||
-rw-r--r-- | mysql-test/main/group_min_max.test | 11 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/MDEV-30804.result | 11 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/MDEV-30804.cnf | 7 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/MDEV-30804.test | 21 | ||||
-rw-r--r-- | sql/handler.cc | 14 | ||||
-rw-r--r-- | sql/opt_range.cc | 46 | ||||
-rw-r--r-- | storage/innobase/trx/trx0purge.cc | 14 | ||||
-rw-r--r-- | storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result | 21 | ||||
-rw-r--r-- | storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test | 29 |
10 files changed, 165 insertions, 21 deletions
diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result index af9f2767a6c..d382ff408eb 100644 --- a/mysql-test/main/group_min_max.result +++ b/mysql-test/main/group_min_max.result @@ -4083,6 +4083,18 @@ MIN(pk) 1 DROP TABLE t1, t2; # +# MDEV-30605 Wrong result while using index for group-by +# +CREATE TABLE t1 (pk INT primary key, a int, key(a)) engine=innodb; +INSERT INTO t1 VALUES (1,-1),(2,8),(3,5),(4,-1),(5,10), (6,-1); +SELECT MIN(pk), a FROM t1 WHERE pk <> 1 GROUP BY a; +MIN(pk) a +4 -1 +3 5 +2 8 +5 10 +DROP TABLE t1; +# # End of 10.5 tests # # diff --git a/mysql-test/main/group_min_max.test b/mysql-test/main/group_min_max.test index 0fa91e4d72b..1bc334dd3da 100644 --- a/mysql-test/main/group_min_max.test +++ b/mysql-test/main/group_min_max.test @@ -1739,6 +1739,17 @@ SELECT MIN(pk) FROM t1, t2; DROP TABLE t1, t2; --echo # +--echo # MDEV-30605 Wrong result while using index for group-by +--echo # + +CREATE TABLE t1 (pk INT primary key, a int, key(a)) engine=innodb; +INSERT INTO t1 VALUES (1,-1),(2,8),(3,5),(4,-1),(5,10), (6,-1); + +SELECT MIN(pk), a FROM t1 WHERE pk <> 1 GROUP BY a; + +DROP TABLE t1; + +--echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/suite/galera/r/MDEV-30804.result b/mysql-test/suite/galera/r/MDEV-30804.result new file mode 100644 index 00000000000..2bf323d19f8 --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-30804.result @@ -0,0 +1,11 @@ +connection node_2; +connection node_1; +CREATE TABLE t (a INT) ENGINE=Aria; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +START TRANSACTION; +INSERT INTO t VALUES ('1'); +INSERT INTO t1 VALUES ('1'); +COMMIT; +ERROR HY000: Transactional commit not supported by involved engine(s) +DROP TABLE t; +DROP TABLE t1; diff --git a/mysql-test/suite/galera/t/MDEV-30804.cnf b/mysql-test/suite/galera/t/MDEV-30804.cnf new file mode 100644 index 00000000000..9dbd81f758d --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-30804.cnf @@ -0,0 +1,7 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +log-bin + +[mysqld.2] +log-bin diff --git a/mysql-test/suite/galera/t/MDEV-30804.test b/mysql-test/suite/galera/t/MDEV-30804.test new file mode 100644 index 00000000000..561953a0578 --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-30804.test @@ -0,0 +1,21 @@ +# +# Test that transaction requiring two-phase commit and involving +# storage engines not supporting it rolls back with a message. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc +--source include/have_aria.inc + +CREATE TABLE t (a INT) ENGINE=Aria; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; + +START TRANSACTION; +INSERT INTO t VALUES ('1'); +INSERT INTO t1 VALUES ('1'); + +--error ER_ERROR_DURING_COMMIT +COMMIT; + +DROP TABLE t; +DROP TABLE t1; diff --git a/sql/handler.cc b/sql/handler.cc index 5246d92138b..b3b22874735 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1824,7 +1824,19 @@ int ha_commit_trans(THD *thd, bool all) ordering is normally done. Commit ordering must be done here. */ if (run_wsrep_hooks) - error= wsrep_before_commit(thd, all); + { + // This commit involves more than one storage engine and requires + // two phases, but some engines don't support it. + // Issue a message to the client and roll back the transaction. + if (trans->no_2pc && rw_ha_count > 1) + { + my_message(ER_ERROR_DURING_COMMIT, "Transactional commit not supported " + "by involved engine(s)", MYF(0)); + error= 1; + } + else + error= wsrep_before_commit(thd, all); + } if (error) { ha_rollback_trans(thd, FALSE); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index c845147e328..44cf08d9323 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -461,7 +461,7 @@ void print_range_for_non_indexed_field(String *out, Field *field, static void print_min_range_operator(String *out, const ha_rkey_function flag); static void print_max_range_operator(String *out, const ha_rkey_function flag); -static bool is_field_an_unique_index(RANGE_OPT_PARAM *param, Field *field); +static bool is_field_an_unique_index(Field *field); /* SEL_IMERGE is a list of possible ways to do index merge, i.e. it is @@ -7752,8 +7752,13 @@ SEL_TREE *Item_func_ne::get_func_mm_tree(RANGE_OPT_PARAM *param, If this condition is a "col1<>...", where there is a UNIQUE KEY(col1), do not construct a SEL_TREE from it. A condition that excludes just one row in the table is not selective (unless there are only a few rows) + + Note: this logic must be in sync with code in + check_group_min_max_predicates(). That function walks an Item* condition + and checks if the range optimizer would produce an equivalent range for + it. */ - if (is_field_an_unique_index(param, field)) + if (param->using_real_indexes && is_field_an_unique_index(field)) DBUG_RETURN(NULL); DBUG_RETURN(get_ne_mm_tree(param, field, value, value)); } @@ -7865,7 +7870,7 @@ SEL_TREE *Item_func_in::get_func_mm_tree(RANGE_OPT_PARAM *param, - if there are a lot of constants, the overhead of building and processing enormous range list is not worth it. */ - if (is_field_an_unique_index(param, field)) + if (param->using_real_indexes && is_field_an_unique_index(field)) DBUG_RETURN(0); /* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */ @@ -8574,24 +8579,18 @@ SEL_TREE *Item_equal::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr) In the future we could also add "almost unique" indexes where any value is present only in a few rows (but necessarily exactly one row) */ -static bool is_field_an_unique_index(RANGE_OPT_PARAM *param, Field *field) +static bool is_field_an_unique_index(Field *field) { DBUG_ENTER("is_field_an_unique_index"); - - // The check for using_real_indexes is there because of the heuristics - // this function is used for. - if (param->using_real_indexes) + key_map::Iterator it(field->key_start); + uint key_no; + while ((key_no= it++) != key_map::Iterator::BITMAP_END) { - key_map::Iterator it(field->key_start); - uint key_no; - while ((key_no= it++) != key_map::Iterator::BITMAP_END) + KEY *key_info= &field->table->key_info[key_no]; + if (key_info->user_defined_key_parts == 1 && + (key_info->flags & HA_NOSAME)) { - KEY *key_info= &field->table->key_info[key_no]; - if (key_info->user_defined_key_parts == 1 && - (key_info->flags & HA_NOSAME)) - { - DBUG_RETURN(true); - } + DBUG_RETURN(true); } } DBUG_RETURN(false); @@ -13475,7 +13474,7 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, - (C between const_i and const_j) - C IS NULL - C IS NOT NULL - - C != const + - C != const (unless C is the primary key) SA4. If Q has a GROUP BY clause, there are no other aggregate functions except MIN and MAX. For queries with DISTINCT, aggregate functions are allowed. @@ -14358,6 +14357,17 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item, if (!simple_pred(pred, args, &inv)) DBUG_RETURN(FALSE); + /* + Follow the logic in Item_func_ne::get_func_mm_tree(): condition + in form "tbl.primary_key <> const" is not used to produce intervals. + + If the condition doesn't have an equivalent interval, this means we + fail LooseScan's condition SA3. Return FALSE to indicate this. + */ + if (pred_type == Item_func::NE_FUNC && + is_field_an_unique_index(min_max_arg_item->field)) + DBUG_RETURN(FALSE); + if (args[0] && args[1]) // this is a binary function or BETWEEN { DBUG_ASSERT(pred->fixed_type_handler()); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 6bdfaa95241..ded4d63d705 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -428,18 +428,28 @@ trx_purge_free_segment(mtr_t &mtr, trx_rseg_t* rseg, fil_addr_t hdr_addr) block->page.frame, &mtr)) { block->fix(); + const page_id_t id{block->page.id()}; mtr.commit(); /* NOTE: If the server is killed after the log that was produced up to this point was written, and before the log from the mtr.commit() in our caller is written, then the pages belonging to the undo log will become unaccessible garbage. - This does not matters when using multiple innodb_undo_tablespaces; + This does not matter when using multiple innodb_undo_tablespaces; innodb_undo_log_truncate=ON will be able to reclaim the space. */ log_free_check(); mtr.start(); block->page.lock.x_lock(); - mtr.memo_push(block, MTR_MEMO_PAGE_X_MODIFY); + if (UNIV_UNLIKELY(block->page.id() != id)) + { + block->unfix(); + block->page.lock.x_unlock(); + block= buf_page_get_gen(id, 0, RW_X_LATCH, nullptr, BUF_GET, &mtr, &err); + if (!block) + return err; + } + else + mtr.memo_push(block, MTR_MEMO_PAGE_X_MODIFY); } while (!fseg_free_step(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + diff --git a/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result b/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result new file mode 100644 index 00000000000..c4399ddf9d2 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/self_reference_multi.result @@ -0,0 +1,21 @@ +for master_1 +for child2 +for child3 + +MDEV-6268 SPIDER table with no COMMENT clause causes queries to wait forever + +CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 (c int); +create table t1 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +create table t0 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +alter table t2 ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t0"'; +select * from t0; +ERROR HY000: An infinite loop is detected when opening table test.t0 +select * from t1; +ERROR HY000: An infinite loop is detected when opening table test.t0 +select * from t2; +ERROR HY000: An infinite loop is detected when opening table test.t0 +drop table t0, t1, t2; +for master_1 +for child2 +for child3 diff --git a/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test b/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test new file mode 100644 index 00000000000..8b6f070d167 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/self_reference_multi.test @@ -0,0 +1,29 @@ +--disable_query_log +--disable_result_log +--source ../../t/test_init.inc +--enable_result_log +--enable_query_log + +--echo +--echo MDEV-6268 SPIDER table with no COMMENT clause causes queries to wait forever +--echo + +--replace_regex /SOCKET ".*"/SOCKET "$MASTER_1_MYSOCK"/ +eval CREATE SERVER srv FOREIGN DATA WRAPPER MYSQL OPTIONS (SOCKET "$MASTER_1_MYSOCK", DATABASE 'test',user 'root'); +create table t2 (c int); +create table t1 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t2"'; +create table t0 (c int) ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t1"'; +alter table t2 ENGINE=Spider COMMENT='WRAPPER "mysql", srv "srv",TABLE "t0"'; +--error 12719 +select * from t0; +--error 12719 +select * from t1; +--error 12719 +select * from t2; +drop table t0, t1, t2; + +--disable_query_log +--disable_result_log +--source ../../t/test_deinit.inc +--enable_result_log +--enable_query_log |