mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge 10.1 into 10.2
This commit is contained in:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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
|
||||
|
@ -2143,6 +2143,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 #
|
||||
|
@ -1824,6 +1824,32 @@ CREATE TABLE t1 (a DECIMAL(2,1) DEFAULT 0.10001e0);
|
||||
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
|
||||
|
@ -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 ||
|
||||
|
@ -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)
|
||||
|
13
sql/table.h
13
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 */
|
||||
|
@ -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 we didn't find any space return iops */
|
||||
if (state->space) {
|
||||
fil_space_release(state->space);
|
||||
state->space = NULL;
|
||||
}
|
||||
|
||||
/* no work to do; release our allocation of I/O capacity */
|
||||
fil_crypt_return_iops(state);
|
||||
|
||||
return false;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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 we didn't find any space return iops */
|
||||
if (state->space) {
|
||||
fil_space_release(state->space);
|
||||
state->space = NULL;
|
||||
}
|
||||
|
||||
/* no work to do; release our allocation of I/O capacity */
|
||||
fil_crypt_return_iops(state);
|
||||
|
||||
return false;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user