Home - Waterfall Grid T-Grid Console Builders Recent Builds Buildslaves Changesources - JSON API - About

Console View


Categories: connectors experimental galera main
Legend:   Passed Failed Warnings Failed Again Running Exception Offline No data

connectors experimental galera main
Yuchen Pei
MDEV-24813 [to-squash] Fix replace_regex in autoinc_debug
Oleksandr Byelkin
new CC 3.3
Sergei Golubchik
Revert "MDEV-39622 OBJECT_INSTANCE_BEGIN in P_S are unstable, difficult to compare"

Let's use MySQL's fix for compatibility

This reverts commit 11c41cd93d2c3732862ba043afd18508021440c0.
Rex Johnston
MDEV-39492 Parallel Query: say in the trace what became of the parallel scan

The optimizer trace named a table as chosen_for_parallel_scan and the query then
ran serially, with nothing anywhere saying so. That is not a small blemish: it is
a trace that sends a reader looking in the wrong place, and it did -- the tpch
query below was diagnosed as having picked the wrong driving table when the
driving table was never the problem.

make_join_readinfo() picks the table, and the plan can still change afterwards.
JOIN::optimize_stage2() calls test_if_skip_sort_order() twice after it, and either
call may hand the driving table an ordered index scan so that it supplies the
GROUP BY or the ORDER BY order for free. An ordered scan is not one that can be
handed out in chunks, and nothing was clearing the decision.

So the gate now records a candidate rather than a conclusion, and
optimize_stage2() reports what became of it once the plan has stopped changing:

  parallel_scan_candidate          the gate picked this table
  chosen_for_parallel_scan          and the plan kept it
  parallel_scan_abandoned          or the plan took it away
  parallel_scan_abandoned_because  why -- an index now supplies the GROUP BY
                                    order, the ORDER BY order, or the access path
                                    is no longer a full table scan

chosen_for_parallel_scan therefore now names only tables that really are scanned
in parallel, which is what makes grepping for it worth anything. The reason is
spelled out rather than left to be inferred, and the key is
parallel_scan_abandoned_because rather than "cause" because "cause" already
appears elsewhere in the trace and a reader grepping for it gets other people's
answers -- which happened while writing the test.

JOIN::worker_side_parallel and JOIN_TAB::use_parallel_scan are cleared with it.
Before, they were left set, so do_select() dispatched into run_worker_side_join()
for a plan that was not going to run in parallel: a manager was built and the
engine was asked to partition the B-tree before something further down declined.
That is avoided now by construction -- the flag is what do_select() dispatches on
-- rather than by measurement, since the chunk counter is only read once workers
have been allocated and reads zero either way.

Worth recording how close this was to being a wrong-results bug rather than a
misleading one. The flag surviving meant the workers could be asked to feed a plan
whose driving table was now expected to arrive in index order. What stops that
today is the check added by "GROUP BY", which declines a plan whose terminal
compares each row with the previous one. Before that existed, this would have
answered wrongly.

Reduced from the tpch query it was found on -- a materialised IN subquery over
LINEITEM grouping by the leading column of its primary key -- to
main.parallel_query_excluded: 40000 rows, GROUP BY the leading key column, and a
LIMIT to make the ordered scan the cheaper plan. It reports candidate 1, chosen 0,
abandoned 1 with the reason, and no workers started. The same table without the
LIMIT keeps the temp-table plan and reports candidate 1, chosen 1, abandoned 0.

This commit was prepared with Claude Code: the misdiagnosis was its own to
correct, and it did so by running the query rather than by reading the trace --
EXPLAIN showed the outer query's driving table as a plain ALL and the counters
showed no parallel execution at all, which located the stale decision in a
subquery nobody was looking at.
bsrikanth-mariadb
MDEV-40388: sequence.simple fails on replay

The problem is that, when recording is enabled for the query such as,
explain select * from seq_1_to_10;
it recorded the table context having a DDL definition as: -

CREATE TABLE `seq_1_to_10` (
    ->  `seq` bigint(20) unsigned NOT NULL,
    ->  PRIMARY KEY (`seq`)
    -> ) ENGINE=SEQUENCE DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;

Now, when that context is replayed, the DDL statement is executed.
But, we cannot create such a table, and instead it errors out saying
ERROR 1050 (42S01): Table 'seq_1_to_10' already exists.

Solution is to use: -
  CREATE TABLE IF NOT EXISTS seq_1_to_10 ...;

=====

Also, there is a different way to use sequences as: -
  Create sequence s1;
  Explain select * from s1;

Here, we should be recording the DDL statement, but no need to store the
stats for it. However, we didn't record the DDL statement earlier.
Moreover, sequence's next value should be the same in the replay environment.

Solution here is to record the DDL for such a sequence as
  CREATE TABLE IF NOT EXISTS s1 ...;
and also set its start value as the recorded environment's previous value using
  SELECT SETVAL(s1, prev_value);
Yuchen Pei
MDEV-24813 [to-squash] Fix replace_regex in autoinc_debug

For windows %p in `fprintf(f, "TRANSACTION (%p)", trx);` is not
prefixed with 0x, so we add a replacement /TRANSACTION
\([0-9A-F]{8}[0-9A-F]*\)/TRANSACTION (0xTHD)/. We use 8 as the minimum
length because not requiring one could cause something like
TRANSACTION (3) to be replaced with TRANSACTION (0xTHD)
Teemu Ollakka
mysqltest: fix do_exec() status decoding for signal-killed processes

WEXITSTATUS() only produces a meaningful value when the process
exited normally. If the command was killed by a signal, it silently
returned status 0, hiding the failure. Check WIFEXITED/WIFSIGNALED
and map signal deaths to the shell's 128+signal convention.
Teemu Ollakka
mysqltest: fix do_exec() status decoding for signal-killed processes

WEXITSTATUS() only produces a meaningful value when the process
exited normally. If the command was killed by a signal, it silently
returned status 0, hiding the failure. Check WIFEXITED/WIFSIGNALED
and map signal deaths to the shell's 128+signal convention.
Marko Mäkelä
squash! e16b1b4e2739be7bc8e91643b0a71e1f04a1b02f

fil_space_t::create_lsn: Change to Atomic_relaxed
and use this to indicate tablespace creation LSN,
in addition to indicate undo tablespace rebuild LSN.

fil_ibd_create(): Set space->create_lsn after the file
has been created.

InnoDB_backup::step(): Do not attempt to copy beyond the
current end of ROW_FORMAT=COMPRESSED files that use a
page size of 1024 or 2048 bytes.
Teemu Ollakka
Galera MTR: disable SSL by default for SST, guard tests missing stunnel

Set ssl-mode=DISABLED in [sst] across all top-level galera/galera_3nodes
topology .cnf files, so tests no longer implicitly require stunnel via
inherited ssl-ca/ssl-cert/ssl-key. Also add the missing have_stunnel.inc
skip guard to galera_ist_rsync_verify_ca and galera_sst_cn_injection's
rsync combination, which intentionally test SSL SST but were not
skipped when stunnel is absent.
Teemu Ollakka
wsrep_info MTR: disable SSL by default for SST
Sergei Golubchik
BUG#39449066 Refactor performance schema OBJECT_INSTANCE_BEGIN columns

Fix for MariaDB 10.6
Yuchen Pei
MDEV-40486 Length check for vector fields in CREATE TABLE ... SELECT

The changes of MDEV-39558 2b6529426a7e7c65d286e093d84138be9dcc34a3
added length check assertion in Field_varstring constructors, and
length check in type inference for SELECT set operations, to emit
errors before reaching the assertions.

That change caused an error to turn into an assertion failure in a
separate path, when the length limit violation is not detected before
tripping the assertion. So in this patch we fix it by adding an
earlier length check in that path.

Also use max_char_length() instead of max_length. This is a more
accurate length of characters. And add handling of empty string edge
case. Added testcases accordingly.
Daniel Black
MDEV-40630: stunnel as Deb/RPM recommends for rsync sst

stunnel has been a component used by the rsync SST mechanism of galera
but has never been listed as a package dependency.

Since MDEV-28233 corrected a unencrypted fallback in the the case of
stunnel being absent, we add stunnel as a recommendation for Debian and
RPM packages.
Rex Johnston
MDEV-39492 Parallel Query: ORDER BY, where the sort is above the join

The gate refused any query with an ORDER BY. What decides whether one can be
honoured is not the ORDER BY, though: it is where the optimizer put the sort.

A sort applied above the join, to a temp table -- EXPLAIN shows it as "Using
temporary; Using filesort" -- runs on the manager once every row has arrived. The
order the rows arrived in is then irrelevant, so the query runs in the workers and
comes back ordered. That is the same reason an ORDER BY after a GROUP BY has worked
here since GROUP BY did. The optimizer chooses that shape when the order depends on
something the driving table cannot supply, such as a column of an inner table.

A sort applied to the driving table, so that the join consumes it already ordered,
cannot be honoured: the chunks finish in whatever order they finish and no worker
sorts anything. Delivering those would mean each worker sorting its chunk and the
manager merging the sorted streams, which is not built.

So the test is a filesort on a table the workers scan, and not the presence of an
ORDER BY. Nothing else was needed: the sort, the LIMIT and the OFFSET are the
server's own, applied on the manager to rows it has all of.

Where the check goes matters, and the first attempt got it wrong in a way worth
recording. Putting it at execution, beside the existing declines, worked but
reinstated exactly the dishonesty the commit before this one removed: EXPLAIN
printed PARALLEL next to "Using filesort" for a query that then ran serially. The
filesort is attached by make_aggr_tables_info(), which is before execution, so the
answer is knowable at optimize time. The re-validation added in that commit has
moved to after the plan is final and now covers both causes, EXPLAIN says ALL, and
the trace says the rows would have to reach the join sorted. The per-table
DBUG_ASSERT(!tab->filesort) is left as the backstop.

Three existing tests gained parallelism with no change to any value, and two of them
had comments explaining a refusal that no longer applies:

  parallel_query_distinct  two DISTINCT-over-join-ordered shapes now run, the sort
                            landing on the temp table the DISTINCT needs anyway
  parallel_query_group_by  SELECT DISTINCT COUNT(*) ... GROUP BY a ORDER BY 1 now
                            runs
  parallel_query_worker_side  unchanged once EXPLAIN stopped claiming PARALLEL

In forced-worker mode main.log_slow_innodb now returns a different ten rows for
"SELECT c, count(*) FROM t1 GROUP BY c ORDER BY 2 LIMIT 700,10". That is not a
wrong answer: it orders by count(*), every count is 2, so the rows are one large
tie and the query asks for rows 700 to 709 of it. Which ten those are is not
determined by the query, and a plan change is free to pick a different ten. Normal
mode passes at 2110.

This commit was prepared with Claude Code: it established by measurement which of
the three ORDER BY shapes can be honoured before writing anything -- lifting the
gate's refusal showed one running correctly and the other two tripping the
inertness assertion, which is what identified the filesort rather than the ORDER BY
as the thing to test for. It also nearly shipped the distinct test with correct
results and stale prose, an edit having silently not applied; re-recording makes a
test pass, it does not make it true.
Daniel Black
MDEV-40630: stunnel as Deb/RPM requirement for rsync sst

Since mariadb-server-galera is a package as of 12.3, we've
added the stunnel as a requirement of this version.

MDEV-28233 ensured that those with a TLS configuration for
the rsync SST mechanism, required that the stunnel executable
existed. It previously would fall back to unencrypted.

As a protection for those using a SST mechanism of rsync (default)
this ensure that the stunnel executable is installed.
Alexander Barkov
MDEV-39587 Package-wide TYPE for variable declarations

SET sql_mode=ORACLE;
DELIMITER $$
CREATE OR REPLACE PACKAGE pkg AS
  -- Declare a package public data type
  TYPE varchar_array IS TABLE OF VARCHAR(2000) INDEX BY INTEGER;
END;
$$
DELIMITER ;
DELIMITER $$

CREATE OR REPLACE PROCEDURE p1 AS
  v pkg.varchar_array; -- Use the package public data type
BEGIN
  v(0):='test';
  SELECT v(0);
END;
$$
DELIMITER ;

Note, the change is done only for sql_mode=ORACLE, because the TYPE
declaration is not available for the default mode.

Where package-wide types are available
--------------------------------------
- Variabe list type:
    DECLARE var pkg1.type1;

- RETURN type for a package routine:
    CREATE FUNCTION .. RETURN pkg1.type1 ...

- Parameter type for a package routine:
    PROCEDURE p1(param1 pkg1.type1);

- Assoc array element type:
    TYPE assoc1_t IS TABLE OF pkg1.type1 ...

- REF CURSOR RETURN type:
    TYPE cur1_t IS REF CURSOR RETURN pkg1.type1;

Change details
--------------

- Adding a member Lex_length_and_dec_st::m_foreign_module_type
  It's set to true when the data type was initialized from a TYPE
  in foreign routine (e.g. in PACKAGE spec).
  It's needed to prevent use of qualified identifiers in public contexts,
  i.e. in schema public routine parameter types and schema publuc function
  RETURN types.
  Adding a helper method sp_head::check_applicability() which prevents
  use of qualified types in public context.

- Adding a helper method sp_head::raise_unknown_data_type().

- Adding methods LEX::set_field_type_typedef_package_spec() for
  2-step and 3-step qualified indentifiers.
  It's used in field_type_all_with_typedefs which covers cases:
  - Variabe list type        : DECLARE var pkg1.type1;
  - RETURN type              : CREATE FUNCTION .. RETURN pkg1.type1 ...
  - Parameter type          : PROCEDURE p1(param1 pkg1.type1);
  - Assoc array element type : TYPE assoc1_t IS TABLE OF pkg1.type1 ...

- Adding a method LEX::declare_type_ref_cursor_return_typedef().
  It handles cases when a new TYPE REF CURSOR RETURN is declared,
  for both for qualified RETURN types and non-qualified RETURN types:
  - TYPE cur0_t IS REF CURSOR RETURN rec1_t;
  - TYPE cur0_t IS REF CURSOR RETURN pkg1.rec1_t;
  - TYPE cur0_t IS REF CURSOR RETURN db1.pkg1.rec1_t;

  The code was moved from LEX::declare_type_ref_cursor() into
  LEX::declare_type_ref_cursor_return_typedef() and extended
  to cover qualified RETURN types.

- Adding a method Sql_path::find_package_spec_type().
  It iterates through all schemas specified in @@path and searches
  for the given type in the given package.

- Adding a helper method sp_pcontext::type_defs_add_ref_cursor()
  to reuse the code.

- Adding a new method sp_package::get_typedef() to search
  for TYPE definitions in PACKAGE specifications.

- Adding a new method sp_head::get_typedef_package_spec()
  to search for TYPE definitions used by a PROCEDURE or FUNCTION.

- Adding a helper method
    Sp_handler::sp_cache_routine_reentrant_suppress_errors
  Adding a method Sp_handler::find_package_spec().
bsrikanth-mariadb
MDEV-40383:innodb_gis.point_basic fails on replay

There are 2 problems: -
1. The REPLACE statement that is recorded doesn't store the
  value of geometry type field correctly.
2. The table definition that got recorded has fields with non-null constraint,
  and no default value is specified.
  Also, the "REPLACE INTO" statement that gets stored in the context,
  doesn't have any value specified for these non-null fields.

Solution is to: -
1. When using REPLACE INTO statement, store all the non-numeric values in HEX,
  whenever conversion from field's charset to output's charset is lossy.
2. Instead of storing only the column values that were projected in the
  query, store all the non-virtual column values into the recorded
  REPLACE INTO statement.

Implementation details: -
1. Introduce a new method is_charset_conversion_lossless() in filesort.cc,
  to check if the output charset to which field's data is being written to,
  results in a lossless conversion. If so, non-numeric values being witten
  using REPLACE INTO statement are stored in string representation,
  else they are converted to HEX.
2. From join_read_const(), and join_read_system() methods in sql_select.cc
  re-read the const row for all the non-virtual fields in the table.
  Similarly, for min/max optimization in opt_sum_query() of opt)_sum.cc,
  include all the non-virtual fields to be dumped into the "REPLACE INTO"
  statement.
  After the row is re-read and recorded, restore the table->read_set,
  table->status, and the const row, to the value that was before with
  the help of widen_read_set_no_vcols() method.
Oleksandr Byelkin
Merge branch '10.11' into bb-10.11-release
Yuchen Pei
MDEV-40631 Fix view protocol for main.partition_range_interval

For the timeout happening in SELECT statements inside a LOCK TABLE /
UNLOCK TABLES block, likely caused by lock conflicts in the service
connection.

For SHOW CREATE TABLE result mismatch, likely caused by the service
connection timestamp being the actual time
Rex Johnston
MDEV-39492 Parallel Query: clone the expression an Item_cache caches

A worker filters by its own copy of the condition, and the copy has to own
every node of it. A shared leaf is repointed at one worker's tables and then at
the next worker's, taking the manager's own item with it, and a shared node
that is not a leaf carries evaluation state that several workers write at once.
So the gate refuses a condition whose copy still reaches the original, and the
query runs serially.

Every Item_cache implemented deep_copy() as a shallow copy. 'example' is an
ordinary pointer, so the copy came back reading the very expression the
original caches: the two shared every node below the cache, and the condition
was refused.

That mattered much more than the class name suggests. JOIN::cache_const_exprs()
wraps each constant subexpression of a WHERE, HAVING or ON in an Item_cache so
that it is evaluated once rather than once per row, and
cache_const_expr_analyzer() exempts only basic constants. A bare
DATE'1998-12-01' was therefore accepted while

  l_shipdate <= DATE'1998-12-01' - INTERVAL '63' DAY

was not, the subtraction being a constant Item_func and so getting a cache. Nor
was q <= 3 + 4: the refusal had nothing to do with dates and covered any
condition holding a constant subexpression, which is most of TPC-H.

Item_cache::deep_copy() now clones 'example' the way
Item_func_or_sum::deep_copy() clones its arguments, preserving the relation
setup() establishes between 'example' and 'cached_field', and reporting an
expression it cannot clone -- a subquery, say -- as an unclonable cache instead
of half copying it. One definition serves the whole family, because
shallow_copy_with_checks() dispatches to each class's own shallow_copy(), so the
per-class deep_copy() overrides are gone. Item_cache_row keeps its own, its
per-column caches living in values[] rather than under 'example'.
Item_cache_year had no shallow_copy() at all and would have been copied as an
Item_cache_int, tripping the type assertion in shallow_copy_with_checks().

Cloning the cached expression reaches items a shallow copy never touched, and
two pieces of Item_sum state were shared where they must not be. 'orig_args'
addresses tmp_orig_args inside the object itself, so a copied pointer left the
clone handing out the original's array through get_args() and writing into it
from fix_fields(). The aggregator, and the Arg_comparator that Item_sum_min_max
binds to its own 'value' and 'arg_cache', are deleted by cleanup(), and with
both items on the statement's free list the one object was deleted twice. That
surfaced as a crash in main.derived_cond_pushdown on

  SELECT * FROM (SELECT DISTINCT * FROM t1) sq WHERE i IN (SELECT MIN(j) FROM t2)

as soon as the cache over MIN(j) began to be cloned. Item_sum::deep_copy() gives
the clone its own orig_args and its own aggregator, as
Item_sum::Item_sum(THD*, Item_sum*) already does for the ROLLUP copies, and
Item_sum_min_max::deep_copy() calls setup_hybrid() to build the comparator
together with the two caches it is bound to. A clone of a fixed item is fixed,
so fix_fields() will not do it.

main.parallel_query_clone covers the five cache classes a constant
subexpression produces, each of which reported ALL before and PARALLEL now, and
compares the answers against a serial run.

This commit was prepared with Claude Code: it located the refusal by dumping the
original and copied item trees with their addresses, which showed the cache
copied and everything below it shared; wrote the Item_cache fix and the Item_sum
fixes that fix exposed; and ran the SQL-layer suites under both protocols.
Marko Mäkelä
MDEV-40596 clang-23 reports unused global variables

Let us remove a number of unused variables to suppress
-Wunused-but-set-global and other warnings.

test_thread(): Instead of incrementing a global counter in a race
condition prone fashion, invoke MY_RELAX_CPU() in order to spend some time.
Yuchen Pei
MDEV-40631 Fix view protocol for main.partition_range_interval

For the timeout happening in SELECT statements inside a LOCK TABLE /
UNLOCK TABLES block, likely caused by lock conflicts in the service
connection.

For SHOW CREATE TABLE result mismatch, likely caused by the service
connection timestamp being the actual time
Sergei Golubchik
MDEV-40571 insufficient validation of frm data when opening a table

numerous checks that the frm is valid, no OOB reads,
values make sense (number of keyparts not less than number of keys,
no keys means no keyparts, number of long unique fields is not larger than
number of fields, fields values in the record don't overlap and don't
go over record ends, and so on). most asserts were changed to if()'s
Yuchen Pei
MDEV-24813 Signal full scan to storage engines.

When starting to do a full table/index scan without a WHERE or JOIN
condition, tell the storage engine so and the corresponding
ulong-truncated LIMIT.

Include an innodb implementation: added an innodb switch
table_lock_on_full_scan, so that when the switch is on, on receiving
the full scan signal from the sql layer, if the truncated LIMIT is
ULONG_MAX (likely no LIMIT), attempt to acquire a table lock.

Updated tests that have different results with the switch on.

The three deadlock_*_race tests cannot reach their DEBUG_SYNC race
under a table lock (it degenerates to a timeout), and the three I_S
tests only restate a lock-mode change already covered
by innodb_full_scan.test.

(Comment and code edited by Sergei Petrunia <[email protected]> and
Thirunarayanan Balathandayuthapani <[email protected]>)
Sergei Golubchik
cleanup: sys_vars.secure_file_priv test
Yuchen Pei
MDEV-24813 [to-squash] Fix replace_regex in autoinc_debug
Aleksey Midenkov
MDEV-40480 LOAD DATA leaves a stale STORED generated column after a BEFORE INSERT trigger changes its base column

On the LOAD DATA path the base columns are filled directly from the
input file and fill_record_n_invoke_before_triggers() is then called
with an empty field list (there is no SET clause). After the BEFORE
INSERT trigger changed a base column, the stored generated columns were
not recomputed, so they kept the value derived from the pre-trigger
input (e.g. g=24 instead of 40 for g=v*2 with v set to 20 by the
trigger). A regular INSERT was unaffected.

The recompute was guarded by "fields.elements". That condition is a
leftover from the original computed-columns implementation
(f7a75b999b4), where fill_record_n_invoke_before_triggers() had no
TABLE* argument and had to reverse-derive the table from the first
item of the field list:

    if (fields.elements)
    {
      fld= (Item_field*)f++;
      item_field= fld->field_for_view_update();
      table= item_field->field->table;
      ...
    }

With an empty field list there was no way to obtain the table, so the
recompute was silently skipped. Since bc4a456758c (MDEV-452) the
function receives TABLE* explicitly, which made the whole derivation
dead code (as the in-place DBUG_ASSERT(table == item_field->field->table)
confirmed). Recompute the virtual fields unconditionally on
table->vfield, the same way the Field** overload of
fill_record_n_invoke_before_triggers() already does.
Dmitry Shulga
MDEV-40064: Memory leak with unparseble trigger for startup body

On loading triggers definitions from the data dictionary table mysql.event,
the syntax error that could happen during parsing the trigger body
would result in memory leaks.

Memory leaks occur because an instance of the sp_head class is not destroyed
in case of an error. To fix, destroy an instance of sp_head in case
there is a syntax error in trigger body.
Sergei Golubchik
MDEV-40589 default exclude list for secure-file-priv

don't allow to access /proc if secure-file-priv="",
set secure-file-priv=/ to access everything and disable the exclude list

remove test for a conditon that can no longer happen
Yuchen Pei
MDEV-24813 Signal full scan to storage engines.

When starting to do a full table/index scan without a WHERE or JOIN
condition, tell the storage engine so and the corresponding
ulong-truncated LIMIT.

Include an innodb implementation: added an innodb switch
table_lock_on_full_scan, so that when the switch is on, on receiving
the full scan signal from the sql layer, if the truncated LIMIT is
ULONG_MAX (likely no LIMIT), attempt to acquire a table lock.

Updated tests that have different results with the switch on.

The three deadlock_*_race tests cannot reach their DEBUG_SYNC race
under a table lock (it degenerates to a timeout), and the three I_S
tests only restate a lock-mode change already covered
by innodb_full_scan.test.

(Comment and code edited by Sergei Petrunia <[email protected]> and
Thirunarayanan Balathandayuthapani <[email protected]>)
Oleksandr Byelkin
Merge branch '10.6' into 10.11
Jan Lindström
Fix test failure on galera_sst_cn_injection test case.

Test requires pkill so skip it is not found from system. Additionally
pkill may fail if socat is not anymore open when pkill executed
(or when socat is not actually used).
Alexey Botchkov
MDEV-39750 ExtractValue does not control recursion depth.

Stack exhaustive test shouldn't be ran with the ASAN/UBSAN.
Daniel Black
MDEV-40630: stunnel as Deb/RPM recommends for rsync sst

stunnel has been a component used by the rsync SST mechanism of galera
but has never been listed as a package dependency.

Since MDEV-28233 corrected a unencrypted fallback in the the case of
stunnel being absent, we add stunnel as a recommendation for Debian and
RPM packages.