diff options
-rw-r--r-- | mysql-test/r/mysqld--help,win.rdiff | 13 | ||||
-rw-r--r-- | mysql-test/r/mysqld--help.result | 4 | ||||
-rw-r--r-- | mysql-test/r/subselect4.result | 41 | ||||
-rw-r--r-- | mysql-test/r/type_newdecimal.result | 47 | ||||
-rw-r--r-- | mysql-test/t/mysqld--help.test | 4 | ||||
-rw-r--r-- | mysql-test/t/subselect4.test | 25 | ||||
-rw-r--r-- | mysql-test/t/type_newdecimal.test | 26 | ||||
-rw-r--r-- | sql/item_subselect.h | 4 | ||||
-rw-r--r-- | sql/sql_union.cc | 19 | ||||
-rw-r--r-- | sql/table.h | 13 | ||||
-rw-r--r-- | storage/innobase/fil/fil0crypt.cc | 122 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 130 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 55 | ||||
-rw-r--r-- | storage/innobase/include/sync0types.h | 1 | ||||
-rw-r--r-- | storage/innobase/sync/sync0debug.cc | 2 | ||||
-rw-r--r-- | storage/xtradb/fil/fil0crypt.cc | 136 | ||||
-rw-r--r-- | storage/xtradb/fil/fil0fil.cc | 134 | ||||
-rw-r--r-- | storage/xtradb/include/fil0fil.h | 28 | ||||
-rw-r--r-- | strings/decimal.c | 18 |
19 files changed, 412 insertions, 410 deletions
diff --git a/mysql-test/r/mysqld--help,win.rdiff b/mysql-test/r/mysqld--help,win.rdiff index 6f151591643..4e93c2ade69 100644 --- a/mysql-test/r/mysqld--help,win.rdiff +++ b/mysql-test/r/mysqld--help,win.rdiff @@ -101,18 +101,7 @@ sort-buffer-size 2097152 sql-mode STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION stack-trace TRUE -@@ -1516,14 +1532,16 @@ - sync-relay-log 10000 - sync-relay-log-info 10000 - sysdate-is-now FALSE --table-cache 421 -+table-cache 2000 - table-definition-cache 400 --table-open-cache 421 --table-open-cache-instances 1 -+table-open-cache 2000 -+table-open-cache-instances 8 - tc-heuristic-recover OFF +@@ -1516,6 +1532,8 @@ thread-cache-size 151 thread-pool-idle-timeout 60 thread-pool-max-threads 65536 diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 283d7a9a3cf..94f2ea0a28c 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1343,7 +1343,6 @@ max-binlog-cache-size 18446744073709547520 max-binlog-size 1073741824 max-binlog-stmt-cache-size 18446744073709547520 max-connect-errors 100 -max-connections 151 max-delayed-threads 20 max-digest-length 1024 max-error-count 64 @@ -1516,10 +1515,7 @@ sync-master-info 10000 sync-relay-log 10000 sync-relay-log-info 10000 sysdate-is-now FALSE -table-cache 421 table-definition-cache 400 -table-open-cache 421 -table-open-cache-instances 1 tc-heuristic-recover OFF thread-cache-size 151 thread-pool-idle-timeout 60 diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index ad8df9f9836..573df11e4a6 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -2609,6 +2609,47 @@ Central America and the Caribbean 442 66422 SET @@optimizer_switch= @save_optimizer_switch; DROP TABLE t1; # +# MDEV-9513: Assertion `join->group_list || !join->is_in_subquery()' failed in create_sort_index +# +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (2),(3); +EXPLAIN +SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY A ALL NULL NULL NULL NULL 2 Using where +3 DEPENDENT UNION B ALL NULL NULL NULL NULL 2 Using where +NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL +SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1); +a +1 +2 +EXPLAIN +SELECT t1.a FROM t1 WHERE EXISTS (SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +2 SUBQUERY A ALL NULL NULL NULL NULL 2 +3 UNION B ALL NULL NULL NULL NULL 2 +NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL +SELECT t1.a FROM t1 WHERE EXISTS (SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1); +a +1 +2 +EXPLAIN +SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION ALL SELECT B.a FROM t2 B ORDER BY 1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where +2 DEPENDENT SUBQUERY A ALL NULL NULL NULL NULL 2 Using where +3 DEPENDENT UNION B ALL NULL NULL NULL NULL 2 Using where +SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION ALL SELECT B.a FROM t2 B ORDER BY 1); +a +1 +2 +DROP TABLE t1,t2; +# end of 10.1 tests +# # MDEV-22852: SIGSEGV in sortlength (optimized builds) # SET @save_optimizer_switch=@@optimizer_switch; diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index e31e0403f80..5c2a41524c1 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -2340,6 +2340,53 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; # +# MDEV-23105 Cast number string with many leading zeros to decimal gives unexpected result +# +SELECT CAST(0000000000000000000000000000000000000000000000000000000000000000000000000000000020.01 AS DECIMAL(15,2)) as val; +val +20.01 +SET sql_mode=''; +CREATE TABLE t1 (a TEXT); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1)); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.0')); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.9')); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.99')); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.994')); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.995')); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.999')); +CREATE TABLE t2 (a TEXT, d DECIMAL(15,2)); +INSERT IGNORE INTO t2 (a,d) SELECT a, a FROM t1; +Warnings: +Note 1265 Data truncated for column 'd' at row 5 +Note 1265 Data truncated for column 'd' at row 6 +Note 1265 Data truncated for column 'd' at row 7 +INSERT IGNORE INTO t2 (a,d) SELECT CONCAT('-',a), CONCAT('-',a) FROM t1; +Warnings: +Note 1265 Data truncated for column 'd' at row 5 +Note 1265 Data truncated for column 'd' at row 6 +Note 1265 Data truncated for column 'd' at row 7 +SELECT d, a FROM t2 ORDER BY d,a; +d a +-2.00 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.995 +-2.00 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.999 +-1.99 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.99 +-1.99 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.994 +-1.90 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.9 +-1.00 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +-1.00 -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.0 +1.00 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 +1.00 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.0 +1.90 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.9 +1.99 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.99 +1.99 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.994 +2.00 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.995 +2.00 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001.999 +DROP TABLE t1, t2; +SET sql_mode=DEFAULT; +# +# End of 10.1 tests +# +# # Bug#18408499 UNSIGNED BIGINT HIGH VALUES # WRONG NUMERICAL COMPARISON RESULTS # diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index 6eb0dc7bb81..12834b6177b 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -23,7 +23,9 @@ perl; log-slow-queries pid-file slow-query-log-file log-basename datadir slave-load-tmpdir tmpdir socket thread-pool-size large-files-support lower-case-file-system system-time-zone - collation-server character-set-server log-tc-size version.*/; + collation-server character-set-server log-tc-size table-cache + table-open-cache table-open-cache-instances max-connections + version.*/; # Plugins which may or may not be there: @plugins=qw/innodb archive blackhole federated partition diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index f35df5b6967..6eada9b27d9 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -2144,6 +2144,31 @@ SET @@optimizer_switch= @save_optimizer_switch; DROP TABLE t1; --echo # +--echo # MDEV-9513: Assertion `join->group_list || !join->is_in_subquery()' failed in create_sort_index +--echo # + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2); + +CREATE TABLE t2 (a INT); +INSERT INTO t2 VALUES (2),(3); +EXPLAIN +SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1); +SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1); + +EXPLAIN +SELECT t1.a FROM t1 WHERE EXISTS (SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1); +SELECT t1.a FROM t1 WHERE EXISTS (SELECT A.a FROM t1 A UNION SELECT B.a FROM t2 B ORDER BY 1); + +EXPLAIN +SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION ALL SELECT B.a FROM t2 B ORDER BY 1); +SELECT t1.a FROM t1 WHERE t1.a IN ( SELECT A.a FROM t1 A UNION ALL SELECT B.a FROM t2 B ORDER BY 1); + +DROP TABLE t1,t2; + +--echo # end of 10.1 tests + +--echo # --echo # MDEV-22852: SIGSEGV in sortlength (optimized builds) --echo # diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index 2f3409f56e9..e5d903e95cd 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1825,6 +1825,32 @@ SHOW CREATE TABLE t1; DROP TABLE t1; --echo # +--echo # MDEV-23105 Cast number string with many leading zeros to decimal gives unexpected result +--echo # + +SELECT CAST(0000000000000000000000000000000000000000000000000000000000000000000000000000000020.01 AS DECIMAL(15,2)) as val; + +SET sql_mode=''; +CREATE TABLE t1 (a TEXT); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1)); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.0')); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.9')); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.99')); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.994')); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.995')); +INSERT INTO t1 VALUES (CONCAT(REPEAT('0',100),1,'.999')); +CREATE TABLE t2 (a TEXT, d DECIMAL(15,2)); +INSERT IGNORE INTO t2 (a,d) SELECT a, a FROM t1; +INSERT IGNORE INTO t2 (a,d) SELECT CONCAT('-',a), CONCAT('-',a) FROM t1; +SELECT d, a FROM t2 ORDER BY d,a; +DROP TABLE t1, t2; +SET sql_mode=DEFAULT; + +--echo # +--echo # End of 10.1 tests +--echo # + +--echo # --echo # Bug#18408499 UNSIGNED BIGINT HIGH VALUES --echo # WRONG NUMERICAL COMPARISON RESULTS --echo # diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 23bdeacade9..816073ed5d3 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -145,6 +145,10 @@ public: Item_subselect(THD *thd); virtual subs_type substype() { return UNKNOWN_SUBS; } + bool is_exists_predicate() + { + return substype() == Item_subselect::EXISTS_SUBS; + } bool is_in_predicate() { return (substype() == Item_subselect::IN_SUBS || diff --git a/sql/sql_union.cc b/sql/sql_union.cc index b2198eb2b31..8b1719c60cb 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -514,6 +514,25 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS; is_union_select= is_union() || fake_select_lex; + /* + If we are reading UNION output and the UNION is in the + IN/ANY/ALL/EXISTS subquery, then ORDER BY is redundant and hence should + be removed. + Example: + select ... col IN (select col2 FROM t1 union select col3 from t2 ORDER BY 1) + + (as for ORDER BY ... LIMIT, it currently not supported inside + IN/ALL/ANY subqueries) + (For non-UNION this removal of ORDER BY clause is done in + check_and_do_in_subquery_rewrites()) + */ + if (is_union() && item && + (item->is_in_predicate() || item->is_exists_predicate())) + { + global_parameters()->order_list.first= NULL; + global_parameters()->order_list.elements= 0; + } + /* Global option */ if (is_union_select || is_recursive) diff --git a/sql/table.h b/sql/table.h index f3a7f278604..14ab0027a79 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1281,9 +1281,16 @@ public: /* number of select if it is derived table */ uint derived_select_number; /* - 0 or JOIN_TYPE_{LEFT|RIGHT}. Currently this is only compared to 0. - If maybe_null !=0, this table is inner w.r.t. some outer join operation, - and null_row may be true. + Possible values: + - 0 by default + - JOIN_TYPE_{LEFT|RIGHT} if the table is inner w.r.t an outer join + operation + - 1 if the SELECT has mixed_implicit_grouping=1. example: + select max(col1), col2 from t1. In this case, the query produces + one row with all columns having NULL values. + + Interpetation: If maybe_null!=0, all fields of the table are considered + NULLable (and have NULL values when null_row=true) */ uint maybe_null; int current_lock; /* Type of lock on table */ diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 8243fa5801d..c687c53ac14 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -41,9 +41,6 @@ Modified Jan Lindström jan.lindstrom@mariadb.com #include "fil0pagecompress.h" #include <my_crypt.h> -/** Mutex for keys */ -static ib_mutex_t fil_crypt_key_mutex; - static bool fil_crypt_threads_inited = false; /** Is encryption enabled/disabled */ @@ -113,8 +110,6 @@ UNIV_INTERN void fil_space_crypt_init() { - mutex_create(LATCH_ID_FIL_CRYPT_MUTEX, &fil_crypt_key_mutex); - fil_crypt_throttle_sleep_event = os_event_create(0); mutex_create(LATCH_ID_FIL_CRYPT_STAT_MUTEX, &crypt_stat_mutex); @@ -128,7 +123,6 @@ void fil_space_crypt_cleanup() { os_event_destroy(fil_crypt_throttle_sleep_event); - mutex_free(&fil_crypt_key_mutex); mutex_free(&crypt_stat_mutex); } @@ -1384,6 +1378,94 @@ fil_crypt_return_iops( fil_crypt_update_total_stat(state); } +/** Return the next tablespace from rotation_list. +@param space previous tablespace (NULL to start from the start) +@param recheck whether the removal condition needs to be rechecked after +the encryption parameters were changed +@param encrypt expected state of innodb_encrypt_tables +@return the next tablespace to process (n_pending_ops incremented) +@retval NULL if this was the last */ +inline fil_space_t *fil_system_t::keyrotate_next(fil_space_t *space, + bool recheck, bool encrypt) +{ + ut_ad(mutex_own(&fil_system->mutex)); + + sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it= + space ? space : fil_system->rotation_list.begin(); + const sized_ilist<fil_space_t, rotation_list_tag_t>::iterator end= + fil_system->rotation_list.end(); + + if (space) + { + while (++it != end && (!UT_LIST_GET_LEN(it->chain) || it->is_stopping())); + + /* If one of the encryption threads already started the encryption + of the table then don't remove the unencrypted spaces from rotation list + + If there is a change in innodb_encrypt_tables variables value then + don't remove the last processed tablespace from the rotation list. */ + if (!--space->n_pending_ops && + (!recheck || space->crypt_data) && !encrypt == !srv_encrypt_tables && + space->is_in_rotation_list) + { + ut_a(!fil_system->rotation_list.empty()); + fil_system->rotation_list.remove(*space); + space->is_in_rotation_list= false; + } + } + + if (it == end) + return NULL; + + space= &*it; + space->n_pending_ops++; + return space; +} + +/** Return the next tablespace. +@param space previous tablespace (NULL to start from the beginning) +@param recheck whether the removal condition needs to be rechecked after +the encryption parameters were changed +@param encrypt expected state of innodb_encrypt_tables +@return pointer to the next tablespace (with n_pending_ops incremented) +@retval NULL if this was the last */ +static fil_space_t *fil_space_next(fil_space_t *space, bool recheck, + bool encrypt) +{ + mutex_enter(&fil_system->mutex); + ut_ad(!space || space->n_pending_ops); + + if (!srv_fil_crypt_rotate_key_age) + space= fil_system->keyrotate_next(space, recheck, encrypt); + else if (!space) + { + space= UT_LIST_GET_FIRST(fil_system->space_list); + /* We can trust that space is not NULL because at least the + system tablespace is always present and loaded first. */ + space->n_pending_ops++; + } + else + { + ut_ad(space->n_pending_ops > 0); + /* Move on to the next fil_space_t */ + space->n_pending_ops--; + space= UT_LIST_GET_NEXT(space_list, space); + + /* Skip abnormal tablespaces or those that are being created by + fil_ibd_create(), or being dropped. */ + while (space && + (UT_LIST_GET_LEN(space->chain) == 0 || + space->is_stopping() || space->purpose != FIL_TYPE_TABLESPACE)) + space= UT_LIST_GET_NEXT(space_list, space); + + if (space) + space->n_pending_ops++; + } + + mutex_exit(&fil_system->mutex); + return space; +} + /** Search for a space needing rotation @param[in,out] key_state Key state @param[in,out] state Rotation state @@ -1416,16 +1498,8 @@ static bool fil_crypt_find_space_to_rotate( state->space = NULL; } - /* If key rotation is enabled (default) we iterate all tablespaces. - If key rotation is not enabled we iterate only the tablespaces - added to keyrotation list. */ - if (srv_fil_crypt_rotate_key_age) { - state->space = fil_space_next(state->space); - } else { - state->space = fil_system->keyrotate_next( - state->space, *recheck, - key_state->key_version); - } + state->space = fil_space_next(state->space, *recheck, + key_state->key_version != 0); while (!state->should_shutdown() && state->space) { /* If there is no crypt data and we have not yet read @@ -1443,16 +1517,16 @@ static bool fil_crypt_find_space_to_rotate( return true; } - if (srv_fil_crypt_rotate_key_age) { - state->space = fil_space_next(state->space); - } else { - state->space = fil_system->keyrotate_next( - state->space, *recheck, - key_state->key_version); - } + state->space = fil_space_next(state->space, *recheck, + key_state->key_version != 0); + } + + if (state->space) { + fil_space_release(state->space); + state->space = NULL; } - /* if we didn't find any space return iops */ + /* no work to do; release our allocation of I/O capacity */ fil_crypt_return_iops(state); return false; diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index f9d7070a41b..88e12d3c80b 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -5892,136 +5892,6 @@ fil_space_t::release_free_extents(ulint n_reserved) n_reserved_extents -= n_reserved; } -/** Return the next fil_space_t. -Once started, the caller must keep calling this until it returns NULL. -fil_space_acquire() and fil_space_release() are invoked here which -blocks a concurrent operation from dropping the tablespace. -@param[in] prev_space Pointer to the previous fil_space_t. -If NULL, use the first fil_space_t on fil_system->space_list. -@return pointer to the next fil_space_t. -@retval NULL if this was the last*/ -fil_space_t* -fil_space_next(fil_space_t* prev_space) -{ - fil_space_t* space=prev_space; - - mutex_enter(&fil_system->mutex); - - if (prev_space == NULL) { - space = UT_LIST_GET_FIRST(fil_system->space_list); - - /* We can trust that space is not NULL because at least the - system tablespace is always present and loaded first. */ - space->n_pending_ops++; - } else { - ut_ad(space->n_pending_ops > 0); - - /* Move on to the next fil_space_t */ - space->n_pending_ops--; - space = UT_LIST_GET_NEXT(space_list, space); - - /* Skip spaces that are being created by - fil_ibd_create(), or dropped, or !tablespace. */ - while (space != NULL - && (UT_LIST_GET_LEN(space->chain) == 0 - || space->is_stopping() - || space->purpose != FIL_TYPE_TABLESPACE)) { - space = UT_LIST_GET_NEXT(space_list, space); - } - - if (space != NULL) { - space->n_pending_ops++; - } - } - - mutex_exit(&fil_system->mutex); - - return(space); -} - -/** -Remove space from key rotation list if there are no more -pending operations. -@param[in,out] space Tablespace */ -static -void -fil_space_remove_from_keyrotation(fil_space_t* space) -{ - ut_ad(mutex_own(&fil_system->mutex)); - ut_ad(space); - - if (space->n_pending_ops == 0 && space->is_in_rotation_list) { - ut_a(!fil_system->rotation_list.empty()); - fil_system->rotation_list.remove(*space); - space->is_in_rotation_list = false; - } -} - - -/** Return the next fil_space_t from key rotation list. -Once started, the caller must keep calling this until it returns NULL. -fil_space_acquire() and fil_space_release() are invoked here which -blocks a concurrent operation from dropping the tablespace. -@param[in] prev_space Previous tablespace or NULL to start - from beginning of fil_system->rotation list -@param[in] recheck recheck of the tablespace is needed or - still encryption thread does write page0 for it -@param[in] key_version key version of the key state thread -If NULL, use the first fil_space_t on fil_system->space_list. -@return pointer to the next fil_space_t. -@retval NULL if this was the last */ -fil_space_t *fil_system_t::keyrotate_next(fil_space_t *prev_space, - bool recheck, uint key_version) -{ - mutex_enter(&fil_system->mutex); - - /* If one of the encryption threads already started the encryption - of the table then don't remove the unencrypted spaces from rotation list - - If there is a change in innodb_encrypt_tables variables value then - don't remove the last processed tablespace from the rotation list. */ - const bool remove= (!recheck || prev_space->crypt_data) && - !key_version == !srv_encrypt_tables; - sized_ilist<fil_space_t, rotation_list_tag_t>::iterator it= - prev_space == NULL ? fil_system->rotation_list.end() : prev_space; - - if (it == fil_system->rotation_list.end()) - { - it= fil_system->rotation_list.begin(); - } - else - { - ut_ad(prev_space->n_pending_ops > 0); - - /* Move on to the next fil_space_t */ - prev_space->n_pending_ops--; - - ++it; - - while (it != fil_system->rotation_list.end() && - (UT_LIST_GET_LEN(it->chain) == 0 || it->is_stopping())) - { - ++it; - } - - if (remove) - { - fil_space_remove_from_keyrotation(prev_space); - } - } - - fil_space_t *space= it == fil_system->rotation_list.end() ? NULL : &*it; - - if (space) - { - space->n_pending_ops++; - } - - mutex_exit(&fil_system->mutex); - - return space; -} - /** Determine the block size of the data file. @param[in] space tablespace @param[in] offset page number diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 585a284798e..e85340d1c4d 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -556,24 +556,15 @@ struct fil_system_t { @retval NULL if the tablespace does not exist or cannot be read */ fil_space_t* read_page0(ulint id); - /** Return the next fil_space_t from key rotation list. - Once started, the caller must keep calling this until it returns NULL. - fil_space_acquire() and fil_space_release() are invoked here which - blocks a concurrent operation from dropping the tablespace. - @param[in] prev_space Previous tablespace or NULL to start - from beginning of fil_system->rotation - list - @param[in] recheck recheck of the tablespace is needed or - still encryption thread does write page0 - for it - @param[in] key_version key version of the key state thread - If NULL, use the first fil_space_t on fil_system->space_list. - @return pointer to the next fil_space_t. - @retval NULL if this was the last */ - fil_space_t* keyrotate_next( - fil_space_t* prev_space, - bool remove, - uint key_version); + /** Return the next tablespace from rotation_list. + @param space previous tablespace (NULL to start from the start) + @param recheck whether the removal condition needs to be rechecked after + the encryption parameters were changed + @param encrypt expected state of innodb_encrypt_tables + @return the next tablespace to process (n_pending_ops incremented) + @retval NULL if this was the last */ + inline fil_space_t* keyrotate_next(fil_space_t *space, bool recheck, + bool encrypt); }; /** The tablespace memory cache. This variable is NULL before the module is @@ -803,34 +794,6 @@ fil_space_acquire_for_io(ulint id); void fil_space_release_for_io(fil_space_t* space); -/** Return the next fil_space_t. -Once started, the caller must keep calling this until it returns NULL. -fil_space_acquire() and fil_space_release() are invoked here which -blocks a concurrent operation from dropping the tablespace. -@param[in,out] prev_space Pointer to the previous fil_space_t. -If NULL, use the first fil_space_t on fil_system->space_list. -@return pointer to the next fil_space_t. -@retval NULL if this was the last */ -fil_space_t* -fil_space_next( - fil_space_t* prev_space) - MY_ATTRIBUTE((warn_unused_result)); - -/** Return the next fil_space_t from key rotation list. -Once started, the caller must keep calling this until it returns NULL. -fil_space_acquire() and fil_space_release() are invoked here which -blocks a concurrent operation from dropping the tablespace. -@param[in] prev_space Previous tablespace or NULL to start - from beginning of fil_system->rotation list -@param[in] remove Whether to remove the previous tablespace from - the rotation list -If NULL, use the first fil_space_t on fil_system->space_list. -@return pointer to the next fil_space_t. -@retval NULL if this was the last*/ -fil_space_t* -fil_space_keyrotate_next(fil_space_t* prev_space, bool remove) - MY_ATTRIBUTE((warn_unused_result)); - /** Wrapper with reference-counting for a fil_space_t. */ class FilSpace { diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h index c21f3bbf853..1820642b004 100644 --- a/storage/innobase/include/sync0types.h +++ b/storage/innobase/include/sync0types.h @@ -379,7 +379,6 @@ enum latch_id_t { LATCH_ID_BTR_DEFRAGMENT_MUTEX, LATCH_ID_MTFLUSH_THREAD_MUTEX, LATCH_ID_MTFLUSH_MUTEX, - LATCH_ID_FIL_CRYPT_MUTEX, LATCH_ID_FIL_CRYPT_STAT_MUTEX, LATCH_ID_FIL_CRYPT_DATA_MUTEX, LATCH_ID_FIL_CRYPT_THREADS_MUTEX, diff --git a/storage/innobase/sync/sync0debug.cc b/storage/innobase/sync/sync0debug.cc index 78c3058573f..815e3cee618 100644 --- a/storage/innobase/sync/sync0debug.cc +++ b/storage/innobase/sync/sync0debug.cc @@ -1511,8 +1511,6 @@ sync_latch_meta_init() PFS_NOT_INSTRUMENTED); LATCH_ADD_MUTEX(MTFLUSH_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED); - LATCH_ADD_MUTEX(FIL_CRYPT_MUTEX, SYNC_NO_ORDER_CHECK, - PFS_NOT_INSTRUMENTED); LATCH_ADD_MUTEX(FIL_CRYPT_STAT_MUTEX, SYNC_NO_ORDER_CHECK, PFS_NOT_INSTRUMENTED); LATCH_ADD_MUTEX(FIL_CRYPT_DATA_MUTEX, SYNC_NO_ORDER_CHECK, diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc index 7219e641e30..b38b8778f5b 100644 --- a/storage/xtradb/fil/fil0crypt.cc +++ b/storage/xtradb/fil/fil0crypt.cc @@ -44,15 +44,8 @@ Modified Jan Lindström jan.lindstrom@mariadb.com #include "ha_prototypes.h" // IB_LOG_ #include <my_crypt.h> -/** Mutex for keys */ -static ib_mutex_t fil_crypt_key_mutex; - static bool fil_crypt_threads_inited = false; -#ifdef UNIV_PFS_MUTEX -static mysql_pfs_key_t fil_crypt_key_mutex_key; -#endif - /** Is encryption enabled/disabled */ UNIV_INTERN ulong srv_encrypt_tables = 0; @@ -133,9 +126,6 @@ UNIV_INTERN void fil_space_crypt_init() { - mutex_create(fil_crypt_key_mutex_key, - &fil_crypt_key_mutex, SYNC_NO_ORDER_CHECK); - fil_crypt_throttle_sleep_event = os_event_create(); mutex_create(fil_crypt_stat_mutex_key, @@ -152,7 +142,6 @@ fil_space_crypt_cleanup() { os_event_free(fil_crypt_throttle_sleep_event); fil_crypt_throttle_sleep_event = NULL; - mutex_free(&fil_crypt_key_mutex); mutex_free(&crypt_stat_mutex); } @@ -1451,6 +1440,109 @@ fil_crypt_return_iops( fil_crypt_update_total_stat(state); } +/** Remove space from key rotation list if there are no pending operations. */ +static void fil_space_remove_from_keyrotation(fil_space_t *space) +{ + ut_ad(mutex_own(&fil_system->mutex)); + + if (space->n_pending_ops == 0 && space->is_in_rotation_list) + { + space->is_in_rotation_list= false; + ut_a(UT_LIST_GET_LEN(fil_system->rotation_list) > 0); + UT_LIST_REMOVE(rotation_list, fil_system->rotation_list, space); + } +} + +/** Return the next tablespace from key rotation list. +@param space previous tablespace (NULL to start from the beginning) +@return pointer to the next tablespace (with n_pending_ops incremented) +@retval NULL if this was the last */ +static fil_space_t *fil_space_keyrotate_next(fil_space_t *space) +{ + ut_ad(mutex_own(&fil_system->mutex)); + + if (UT_LIST_GET_LEN(fil_system->rotation_list) == 0) + { + if (space) + { + space->n_pending_ops--; + fil_space_remove_from_keyrotation(space); + } + + return NULL; + } + + if (!space) + { + space= UT_LIST_GET_FIRST(fil_system->rotation_list); + /* We can trust that space is not NULL because we + checked list length above */ + } + else + { + space->n_pending_ops--; + fil_space_t *old = space; + space= UT_LIST_GET_NEXT(rotation_list, space); + fil_space_remove_from_keyrotation(old); + } + + /* Skip spaces that are being created by fil_ibd_create(), + or dropped. Note that rotation_list contains only + space->purpose == FIL_TABLESPACE. */ + while (space && (!UT_LIST_GET_LEN(space->chain) || space->is_stopping())) + { + fil_space_t *old = space; + space= UT_LIST_GET_NEXT(rotation_list, space); + fil_space_remove_from_keyrotation(old); + } + + if (space) + space->n_pending_ops++; + + return space; +} + +/** Return the next tablespace. +@param space previous tablespace (NULL to start from the beginning) +@return pointer to the next tablespace (with n_pending_ops incremented) +@retval NULL if this was the last */ +static fil_space_t *fil_space_next(fil_space_t *space) +{ + mutex_enter(&fil_system->mutex); + ut_ad(!space || space->n_pending_ops); + + if (!srv_fil_crypt_rotate_key_age) + space= fil_space_keyrotate_next(space); + else if (!space) + { + space= UT_LIST_GET_FIRST(fil_system->space_list); + /* We can trust that space is not NULL because at least the + system tablespace is always present and loaded first. */ + space->n_pending_ops++; + } + else + { + ut_ad(space->n_pending_ops > 0); + /* Move on to the next fil_space_t */ + space->n_pending_ops--; + space= UT_LIST_GET_NEXT(space_list, space); + + /* Skip abnormal tablespaces or those that are being created by + fil_ibd_create(), or being dropped. */ + while (space && + (UT_LIST_GET_LEN(space->chain) == 0 || + space->is_stopping() || space->purpose != FIL_TABLESPACE)) + space= UT_LIST_GET_NEXT(space_list, space); + + if (space) + space->n_pending_ops++; + } + + mutex_exit(&fil_system->mutex); + + return space; +} + /*********************************************************************** Search for a space needing rotation @param[in,out] key_state Key state @@ -1485,14 +1577,7 @@ fil_crypt_find_space_to_rotate( state->space = NULL; } - /* If key rotation is enabled (default) we iterate all tablespaces. - If key rotation is not enabled we iterate only the tablespaces - added to keyrotation list. */ - if (srv_fil_crypt_rotate_key_age) { - state->space = fil_space_next(state->space); - } else { - state->space = fil_space_keyrotate_next(state->space); - } + state->space = fil_space_next(state->space); while (!state->should_shutdown() && state->space) { fil_crypt_read_crypt_data(state->space); @@ -1505,14 +1590,15 @@ fil_crypt_find_space_to_rotate( return true; } - if (srv_fil_crypt_rotate_key_age) { - state->space = fil_space_next(state->space); - } else { - state->space = fil_space_keyrotate_next(state->space); - } + state->space = fil_space_next(state->space); + } + + if (state->space) { + fil_space_release(state->space); + state->space = NULL; } - /* if we didn't find any space return iops */ + /* no work to do; release our allocation of I/O capacity */ fil_crypt_return_iops(state); return false; diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index d77d7320318..be11b1089a9 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -6863,137 +6863,3 @@ fil_space_release(fil_space_t* space) space->n_pending_ops--; mutex_exit(&fil_system->mutex); } - -/** Return the next fil_space_t. -Once started, the caller must keep calling this until it returns NULL. -fil_space_acquire() and fil_space_release() are invoked here which -blocks a concurrent operation from dropping the tablespace. -@param[in] prev_space Pointer to the previous fil_space_t. -If NULL, use the first fil_space_t on fil_system->space_list. -@return pointer to the next fil_space_t. -@retval NULL if this was the last*/ -UNIV_INTERN -fil_space_t* -fil_space_next(fil_space_t* prev_space) -{ - fil_space_t* space=prev_space; - - mutex_enter(&fil_system->mutex); - - if (prev_space == NULL) { - space = UT_LIST_GET_FIRST(fil_system->space_list); - - /* We can trust that space is not NULL because at least the - system tablespace is always present and loaded first. */ - space->n_pending_ops++; - } else { - ut_ad(space->n_pending_ops > 0); - - /* Move on to the next fil_space_t */ - space->n_pending_ops--; - space = UT_LIST_GET_NEXT(space_list, space); - - /* Skip spaces that are being created by - fil_ibd_create(), or dropped, or !tablespace. */ - while (space != NULL - && (UT_LIST_GET_LEN(space->chain) == 0 - || space->is_stopping() - || space->purpose != FIL_TABLESPACE)) { - space = UT_LIST_GET_NEXT(space_list, space); - } - - if (space != NULL) { - space->n_pending_ops++; - } - } - - mutex_exit(&fil_system->mutex); - - return(space); -} - -/** -Remove space from key rotation list if there are no more -pending operations. -@param[in] space Tablespace */ -static -void -fil_space_remove_from_keyrotation( - fil_space_t* space) -{ - ut_ad(mutex_own(&fil_system->mutex)); - ut_ad(space); - - if (space->n_pending_ops == 0 && space->is_in_rotation_list) { - space->is_in_rotation_list = false; - ut_a(UT_LIST_GET_LEN(fil_system->rotation_list) > 0); - UT_LIST_REMOVE(rotation_list, fil_system->rotation_list, space); - } -} - - -/** Return the next fil_space_t from key rotation list. -Once started, the caller must keep calling this until it returns NULL. -fil_space_acquire() and fil_space_release() are invoked here which -blocks a concurrent operation from dropping the tablespace. -@param[in] prev_space Pointer to the previous fil_space_t. -If NULL, use the first fil_space_t on fil_system->space_list. -@return pointer to the next fil_space_t. -@retval NULL if this was the last*/ -UNIV_INTERN -fil_space_t* -fil_space_keyrotate_next( - fil_space_t* prev_space) -{ - fil_space_t* space = prev_space; - fil_space_t* old = NULL; - - mutex_enter(&fil_system->mutex); - - if (UT_LIST_GET_LEN(fil_system->rotation_list) == 0) { - if (space) { - ut_ad(space->n_pending_ops > 0); - space->n_pending_ops--; - fil_space_remove_from_keyrotation(space); - } - mutex_exit(&fil_system->mutex); - return(NULL); - } - - if (prev_space == NULL) { - space = UT_LIST_GET_FIRST(fil_system->rotation_list); - - /* We can trust that space is not NULL because we - checked list length above */ - } else { - ut_ad(space->n_pending_ops > 0); - - /* Move on to the next fil_space_t */ - space->n_pending_ops--; - - old = space; - space = UT_LIST_GET_NEXT(rotation_list, space); - - fil_space_remove_from_keyrotation(old); - } - - /* Skip spaces that are being created by fil_ibd_create(), - or dropped. Note that rotation_list contains only - space->purpose == FIL_TABLESPACE. */ - while (space != NULL - && (UT_LIST_GET_LEN(space->chain) == 0 - || space->is_stopping())) { - - old = space; - space = UT_LIST_GET_NEXT(rotation_list, space); - fil_space_remove_from_keyrotation(old); - } - - if (space != NULL) { - space->n_pending_ops++; - } - - mutex_exit(&fil_system->mutex); - - return(space); -} diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 6a823e131ac..78878fa75fc 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -705,34 +705,6 @@ UNIV_INTERN void fil_space_release_for_io(fil_space_t* space); -/** Return the next fil_space_t. -Once started, the caller must keep calling this until it returns NULL. -fil_space_acquire() and fil_space_release() are invoked here which -blocks a concurrent operation from dropping the tablespace. -@param[in,out] prev_space Pointer to the previous fil_space_t. -If NULL, use the first fil_space_t on fil_system->space_list. -@return pointer to the next fil_space_t. -@retval NULL if this was the last */ -UNIV_INTERN -fil_space_t* -fil_space_next( - fil_space_t* prev_space) - MY_ATTRIBUTE((warn_unused_result)); - -/** Return the next fil_space_t from key rotation list. -Once started, the caller must keep calling this until it returns NULL. -fil_space_acquire() and fil_space_release() are invoked here which -blocks a concurrent operation from dropping the tablespace. -@param[in,out] prev_space Pointer to the previous fil_space_t. -If NULL, use the first fil_space_t on fil_system->space_list. -@return pointer to the next fil_space_t. -@retval NULL if this was the last*/ -UNIV_INTERN -fil_space_t* -fil_space_keyrotate_next( - fil_space_t* prev_space) - MY_ATTRIBUTE((warn_unused_result)); - /** Wrapper with reference-counting for a fil_space_t. */ class FilSpace { diff --git a/strings/decimal.c b/strings/decimal.c index 21af3dc8882..2dd7c960a3e 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -812,6 +812,24 @@ internal_str2dec(const char *from, decimal_t *to, char **end, my_bool fixed) while (s < end_of_string && my_isdigit(&my_charset_latin1, *s)) s++; intg= (int) (s-s1); + /* + If the integer part is long enough and it has multiple leading zeros, + let's trim them, so this expression can return 1 without overflowing: + CAST(CONCAT(REPEAT('0',90),'1') AS DECIMAL(10)) + */ + if (intg > DIG_PER_DEC1 && s1[0] == '0' && s1[1] == '0') + { + /* + Keep at least one digit, to avoid an empty string. + So we trim '0000' to '0' rather than to ''. + Otherwise the below code (converting digits to to->buf) + would fail on a fatal error. + */ + const char *iend= s - 1; + for ( ; s1 < iend && *s1 == '0'; s1++) + { } + intg= (int) (s-s1); + } if (s < end_of_string && *s=='.') { endp= s+1; |