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
Thirunarayanan Balathandayuthapani
MDEV-41282 Recursion in InnoDB FTS AST causes stack-overflow (fts_ast_free_node/fts_ast_free_list)

Problem:
=======
fts_ast_free_node() and fts_ast_free_list() called each other, so
releasing the parse tree consumed one pair of thread stack frames
for every level of the tree.  sub_expr: '(' expr_lst ')' creates
one FTS_AST_SUBEXP_LIST per pair of parentheses, so a boolean
mode query with 2000 nested parentheses builds a chain of 4002
nodes, and fts_query_free() overflowed the thread stack
while freeing it.

fts_ast_visit() does not reach that depth, because
fts_ast_visit_sub_exp() limits the sub-expression nesting to
32 levels and returns DB_OUT_OF_MEMORY.
The parser has built the whole tree by then, and  it still has
to be freed.

fts_ast_node_print_recursive() recurses the same way. It is called
from fts_query_parse() when innodb_ft_enable_diag_print is enabled,
so it overflows the stack right after parsing, before the query is
executed.


Solution:
========
fts_ast_free_node(): Free the sub-tree with an explicit stack
instead of by recursion. The stack is threaded through the
next pointer of the very nodes that are about to be freed,
so it needs no extra memory and cannot fail to allocate.
A node is only pushed once it has been detached from the tree.
The children of a list are already chained to each other by next,
so a whole list is spliced onto the stack in one step.

fts_ast_free_list(): Removed, no longer needed.

fts_ast_node_print_recursive(): Stop at FTS_AST_PRINT_MAX_LEVEL and
print "..." instead of descending further.
Thirunarayanan Balathandayuthapani
MDEV-41281 Unbounded Recursion in InnoDB FTS Boolean-Mode causes Stack-Overflow fts_ast_visit

expr_lst: expr_lst sub_expr wrapped the expression list parsed so
far in a newly created FTS_AST_LIST for every sub-expression,
so a query such as '(word)' repeated N times built N nested lists.
fts_ast_visit() recurses once per FTS_AST_LIST and overflowed the
thread stack; the default thread_stack was exhausted at about
2300 repetitions.

Append the sub-expression to the list that is already being built,
and create a list only when there is none yet, the way
the neighbouring expr_lst: expr_lst expr rule has always done.
The sub-expressions now become siblings of a single list and
the depth no longer grows.

This also corrects '+term (subexpr)'. The FTS_EXIST pass used to
run to completion in the inner list before the sub-expression was
unioned at the outer level, so rows that matched only the
sub-expression were returned.

Based on mysql/mysql-server@e46e9db484a051db6ffb0abd2b06d3b38ef71a35
Vladislav Vaintroub
Merge branch '10.11' into 10.11-MDEV-40878
Kristian Nielsen
MDEV-41562: Old slave with semi-sync and binlog-in-engine master

With binlog-in-engine, semi-sync replication is supported only when the
slave (and the master) is at least MariaDB 13.2. So make sure to give an
error if an old slave connects to a master with binlog-in-engine enabled and
the slave has semi-sync enabled.

Signed-off-by: Kristian Nielsen <[email protected]>
Alessandro Vetere
MDEV-41844 Test innodb.buf_pool_resize_pcur_restore is flaky

The procedure read_into_first_new_block() requires that the page of a
table is read into the first block that a buffer pool grow adds. While
history exists, the purge coordinator runs once per second. It reads
undo log pages, and purge_truncation_callback() reads the header page
of each rollback segment. On a slow builder, these reads can take the
first new block in all 5 attempts.

Stop purge for the duration of the test with FLUSH TABLES ... FOR
EXPORT on a separate connection. A read view does not stop these reads.
Remove the wait for purge between the two cases, because purge is
stopped.

Assisted-by: Claude:claude-opus-5-5
Rex Johnston
MDEV-41632 UPPER(key_col) IN (constant subquery) returns incorrect row

Item_func_in::varchar_upper_cmp_transformer() rewrites
UPPER(key_col) IN (const, ...) into key_col IN (const, ...).

It needs a copy of the IN predicate to put the new first argument into,
it used deep_copy_with_checks(). A deep copy copies every node of the tree and
refuses as a whole if any node cannot be copied, so an IN list holding an
uncorrelated scalar subquery, which is constant but has no copy, silently
lost the rewrite: UPPER(a) IN ((SELECT MAX(c) FROM t2),'A-2') read the whole
table instead of using a range on the index on a. After copying, the rewrite
walked the copy with cleanup_excluding_const_fields_processor and re-fixed
it, which would also have cleaned up a subquery had one been copied.

A copy for use in the same SELECT_LEX does not need to copy what can be
shared there. We add a separate copy hierarchy for that purpose.

Item::same_select_copy_with_checks() calls the protected virtual
Item::same_select_copy(), and cleans up every node it actually copied, so
that the caller only has to call fix_fields() on the result. fix_fields()
re-fixes the copied nodes and skips the shared ones, which are still fixed.
It does not use deep_copy() at any level; the only other copy function it
calls is shallow_copy() on the node being copied.

Item default is to share the item.

Item_func, Item_cond and Item_row copy their node and recurse into their
arguments.

Item_func copies an argument that occurs more than once in args[] only once.
Item_bool_rowready_func2, Item_func_case_simple and Item_func_in detach the
comparators and value array they would otherwise share with the original,
as their deep_copy() overrides do.

Fields, references, constants, parameters, caches, subqueries, aggregate and
window functions are shared because they don't derive from Item_func.

Some Item_func subclasses cannot safely be copied, so they override
same_select_copy() to share the original instead:

- Functions that own memory or handles, which the copy would free a
  second time in cleanup() or its destructor: the regex functions, UDFs,
  stored functions, the JSON functions that build hashes, VEC_FromText,
  and the geometry functions with Gcalc state.
- Functions that their SELECT_LEX keeps a pointer to, so a copy would not
  be the item the SELECT_LEX uses: MATCH, ROWNUM and Item_equal.
- Functions whose copy would behave differently: RAND would restart its
  random sequence, and SET @var would assign the variable twice.
- TO_NUMBER, which refuses to be copied at all.
- Functions whose arguments point at each other: NULLIF uses args[0] a
  second time as args[2], and Item_in_optimizer's cache belongs to its
  subquery.

The rewrite now uses same_select_copy_with_checks() and no longer walks the
copy with a cleanup processor.

TABLE::add_splitting_info_for_key_field() uses it too, for the left side of
the equality it pushes into a split-materialized derived table: the item of
the derived table's select list, used in the WHERE condition of the same
select. That item is always a column, so the copy is the column itself,
where the deep copy made a second Item_field for it. The equality is fixed
when it is injected. The split_materialized_clones check of the left side
is removed, as it is no longer meant to be a deep copy.

This commit was prepared with Claude Code (Opus 5), which found the
subquery case that lost the rewrite and confirmed that the new test fails
without the change, designed and wrote the same_select_copy() hierarchy
and the list of shared Item_func classes, switched the casefold rewrite to
it, and ran main and the SQL-layer suites in normal and --ps-protocol mode.
bsrikanth-mariadb
MDEV-41749: FederatedX pushdown sends "<nop>(" in pushed-down SQL

A pushed-down statement containing "x < SOME (subquery)" failed on the
remote server with a syntax error, as the query text contained the
internal "<nop>(...)" wrapper. "x < ALL (subquery)" is wrapped in
"<not>(...)" in the same way.

Item_func_not_all::print() prints the wrapper whenever `show` is set.
Omit it when QT_PARSABLE is requested and print the wrapped predicate in
parentheses, as precedence() reports the wrapper, so a parent expression
would not add parentheses itself.

While the ALL/ANY subquery item is intact, args[0] prints the original
"x op ALL|ANY (subquery)". When the subquery is reduced to a constant
("x < ALL (SELECT 2)"), it is replaced by a comparison with the inverted
comparator, and the negation is held by "<not>". Print it explicitly as
"NOT (x >= 2)" for ALL, otherwise the remote server returns the
complementary rows. ANY/SOME needs no negation.

Item_allany_subselect::print() printed its left operand without
parentheses, so "(a XOR b) < ALL (subquery)" was pushed as
"a xor b < all (...)" and parsed by the remote server as
"a XOR (b < ALL ...)". Use print_parenthesised(), as
Item_in_subselect::print() does.

Add tests to federatedx_pushdown_upd_del covering SOME and ALL in
UPDATE, DELETE and SELECT, with results compared with pushdown OFF and
the pushed-down text checked in the remote general log.
Marko Mäkelä
MDEV-41506: Broken recovery of SET GLOBAL innodb_log_archive=OFF on PMEM

recv_sys_t::find_checkpoint(): When modifying log_sys.archive,
remember to call mtr_t::finisher_update().

mtr_t::finisher_validate(): A validation predicate for srv_start().

Reviewed by: Thirunarayanan Balathandayuthapani
Vladislav Vaintroub
Fix main.grant_repair on Windows when user.MAI ends with Ctrl-Z

The test patches user.MAI from perl, opened in text mode. On Windows
that strips a trailing 0x1A byte on close, so the index file becomes
one byte shorter and the server reports a size mismatch instead of
repairing the table. Open the file with the :raw layer.

Assisted-by: Claude:claude-sonnet-5-5
Jan Lindström
Record test result after protocol change.
Aleksey Midenkov
Fix SSL test failures with GnuTLS client (11.4)

With WITH_SSL=bundled the server uses wolfSSL and Connector/C is
built with GnuTLS. The GnuTLS backend reports a CA-signed server
certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN,
which neither --ssl-fp nor password-based verification can override
(OpenSSL reports it as MARIADB_TLS_VERIFY_TRUST).

The fix:

  main.ssl_fp      skip unless the client uses OpenSSL or LibreSSL
  main.mysql      pass --ssl-ca to a GnuTLS client for the
                  --ssl-verify-server-cert check
  rpl.rpl_semi_sync_no_missed_ack_after_add_slave
                  include default_client.cnf, so check-testcase
                  connects with --disable-ssl-verify-server-cert
                  (also done in 10.11)
Aleksey Midenkov
Fix SSL test failures with GnuTLS client (10.11)

The test .cnf does not include default_client.cnf, so clients do not
get loose-disable-ssl-verify-server-cert. Since 11.4 the client
verifies the server certificate by default. With WITH_SSL=bundled
Connector/C is built with GnuTLS, which reports the CA-signed test
server certificate with an unknown issuer as
MARIADB_TLS_VERIFY_UNKNOWN, so check-testcase fails to connect to
server 2 with "The certificate issuer is unknown".

The fix includes default_client.cnf into the test .cnf, like other
rpl tests do.
sjaakola
MDEV-38981 Galera loses wsrep_gtid_domain_id after pc.recovery restart

Fix for MDEV-24546 changed the storage for wsrep_gtid_domain_id
(either in config file or as an option) to be into wsrep_gtid_domain_id
variable.  And it is copied to wsrep_gtid_server struct's domain_id only
in the variable's ON_UPDATE hookw.

On server startup this struct was set only by the bootstrap (startup with
--wsrep-new-cluster) or by SST/IST donation from the donor.
When all nodes crashed and the cluster re-formed through pc.recovery,
neither of these happened, so wsrep_init_gtid() replaced the recovered
domain with 0. New writes then got domain 0.
And afer this, later joiners also inherited domain 0 from their donor.

The fix here is simply to copy wsrep_gtid_domain_id to wsrep_gtid_server struct
in wsrep_init_server(), before any state transfer.

Commit has a new mtr test: galera.MDEV-38981,
Assisted-by: https://mariadb.org/governance/governance-ai-policy/
Marko Mäkelä
MDEV-41506: Broken recovery of SET GLOBAL innodb_log_archive=OFF on PMEM

recv_sys_t::find_checkpoint(): When modifying log_sys.archive,
remember to call mtr_t::finisher_update().

mtr_t::finisher_validate(): A validation predicate for srv_start().

Reviewed by: Thirunarayanan Balathandayuthapani
Vladislav Vaintroub
Fixup be807b2d047: match GnuTLS only, not every non-OpenSSL client

Schannel on Windows is not OpenSSL either, but handles these cases.

Assisted-by: Claude:claude-sonnet-5-5
Rex Johnston
MDEV-41251 Wrong result with split materialized query

A query like

  SELECT * FROM t0 WHERE t0.b IN
    (SELECT t.n2 FROM t1, (SELECT n1, n2 FROM t1 GROUP BY n1, n2) t
      WHERE t.n1 = t1.n1 AND t1.c1 = 'a' UNION SELECT -1)

returned only the row of t0 that was read first, when the derived table t
was split-materialized.

The IN->EXISTS transformation wraps t0.b in an Item_cache owned by the
Item_in_optimizer, and injects t.n2 = <cache>(t0.b) into the subquery. The
optimizer then pushes an equality on n2 into the derived table, so that
the table only has to be filled with the matching rows.
TABLE::add_splitting_info_for_key_field() built the right side of that
equality as a deep copy of <cache>(t0.b). A copy of a cache is a second
cache: it read t0.b for the first row of t0 and kept that value, because
only the Item_in_optimizer stores new values, and it stores them into the
original cache. Every later refill of the derived table was filtered on
the first row's value.

The right side is an expression of the outer select used inside the select
that specifies the derived table. Add a copy hierarchy for that purpose.
Item::new_select_copy_with_checks(thd, item_select) returns a copy for use
in a select nested in item_select, the select the item belongs to. In the
nested select the copy is an outer reference to item_select:

- An Item_field is copied and its depended_from set to item_select. This is
  what add_splitting_info_for_key_field() did before with
  set_fields_as_dependent_processor, except that depended_from now names
  the select the column belongs to instead of the nested select.
- An Item_direct_view_ref, a column of a merged view or derived table, is
  also copied like a column: the copy refers to a new_select_copy() of the
  item the view column stands for. Copying it this way, as the deep copy
  did, keeps a column of a constant NULL-complemented table constant in the
  pushed equality (the MDEV-30081 test in main.derived_cond_pushdown still
  shows ref "const" for its LATERAL DERIVED table).
- Any other item that depends on tables of item_select is not copied. The
  copy is an Item_direct_ref to the original item, with depended_from set
  to item_select. So the nested select reads the cache, aggregate or
  subquery that its owner keeps up to date, instead of a copy of it that
  nobody refreshes. Item_default_value is treated this way too.
- An item that depends on no table of item_select is shared.

The copy is fixed, and only refers to tables outside the select it is used
in, which the wrapper asserts. add_splitting_info_for_key_field() now uses
it for the right side of the pushed equality, and no longer walks the copy
with set_fields_as_dependent_processor or calls update_used_tables() on
it. The debug-only copy of key_field->val used for the lookup still uses
deep_copy_with_checks(). The check_deep_copy() call on the right side is
removed, as it is no longer meant to be a deep copy.

A second test, taken from Dave Gosselin's MDEV-41251 commit, pushes a
comparison, dt.a <=> (t1.b = 1), and its row form. The deep copy of the
comparison was never fixed again. Its Arg_comparator still pointed at the
original, which sets null_value of the original, and a copied row
comparison had comparators set to NULL. The row of t1 with a NULL b was
missing from the result, and the row form crashed in
Arg_comparator::compare_row(). Now the comparison is not copied: the right
side refers to the original.

This commit was prepared with Claude Code (Opus 5), which designed and
wrote the new_select_copy() hierarchy, switched the split equality to it,
wrote the three-row test from the earlier rr analysis, added the
comparison test, confirmed in a build of the parent commit that both tests
fail without the change, and ran main and the SQL-layer suites in normal
and --ps-protocol mode.
Vladislav Vaintroub
MDEV-40878 avoid repeated parsing of PROXY headers

Do not parse multiple proxy headers. The protocol spec says the header is
at the beginning of a connection, so there could only be one.

According to example in the spec, in multi-layer scenarios, where several
proxies are involved between client and backend, the intermediate proxy
is supposed to be configured to replace the existing header. Thus multiple
headers are not expected.
Aleksey Midenkov
Fix SSL test failures with GnuTLS client

With WITH_SSL=bundled the server uses wolfSSL and Connector/C is
built with GnuTLS. The GnuTLS backend reports a CA-signed server
certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN,
which neither --ssl-fp nor password-based verification can override
(OpenSSL reports it as MARIADB_TLS_VERIFY_TRUST).

The fix:

  main.ssl_fp      skip unless the client uses OpenSSL or LibreSSL
  main.mysql      pass --ssl-ca to a GnuTLS client for the
                  --ssl-verify-server-cert check
  rpl.rpl_semi_sync_no_missed_ack_after_add_slave
                  include default_client.cnf, so check-testcase
                  connects with --disable-ssl-verify-server-cert
                  (also done in 10.11)
Dave Gosselin
MDEV-41746:  IN-subquery not allowed with OFFSET

Prevent OFFSET from appearing in IN, ALL, or ANY subqueries with
error ER_NOT_SUPPORTED_YET.  This mirrors how we prevent LIMIT
from appearing in similar queries.

Previously, OFFSET queries within IN-subqueries could return
wrong results if for example the OFFSET was past the end of the
table.

Also print OFFSET n ROWS when there is no FETCH clause.  Before,
view definitions and EXPLAIN EXTENDED omitted such an OFFSET.  Views
and derived tables with such an OFFSET are no longer merged into the
outer query because merging discarded the OFFSET.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Vladislav Vaintroub
Fix main.grant_repair on Windows when user.MAI ends with Ctrl-Z

The test patches user.MAI from perl, opened in text mode. On Windows
that strips a trailing 0x1A byte on close, so the index file becomes
one byte shorter and the server reports a size mismatch instead of
repairing the table. Open the file with the :raw layer.

Assisted-by: Claude:claude-sonnet-5-5
Dave Gosselin
MDEV-41746:  IN subquery accepted with OFFSET clause

An IN, ALL, or ANY subquery with OFFSET but no LIMIT was accepted and
the OFFSET was ignored, producing wrong results.  The same subquery
with LIMIT is rejected with ER_NOT_SUPPORTED_YET.

st_select_lex::test_limit() now also rejects a subquery that has an
OFFSET, with the message 'OFFSET & IN/ALL/ANY/SOME subquery'.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Thirunarayanan Balathandayuthapani
MDEV-41281 Unbounded Recursion in InnoDB FTS Boolean-Mode causes Stack-Overflow fts_ast_visit

expr_lst: expr_lst sub_expr wrapped the expression list parsed so
far in a newly created FTS_AST_LIST for every sub-expression,
so a query such as '(word)' repeated N times built N nested lists.
fts_ast_visit() recurses once per FTS_AST_LIST and overflowed the
thread stack; the default thread_stack was exhausted at about
2300 repetitions.

Append the sub-expression to the list that is already being built,
and create a list only when there is none yet, the way
the neighbouring expr_lst: expr_lst expr rule has always done.
The sub-expressions now become siblings of a single list and
the depth no longer grows.

This also corrects '+term (subexpr)'. The FTS_EXIST pass used to
run to completion in the inner list before the sub-expression was
unioned at the outer level, so rows that matched only the
sub-expression were returned.

Based on mysql/mysql-server@e46e9db484a051db6ffb0abd2b06d3b38ef71a35
Thirunarayanan Balathandayuthapani
MDEV-41282 Recursion in InnoDB FTS AST causes stack-overflow (fts_ast_free_node/fts_ast_free_list)

Problem:
=======
fts_ast_free_node() and fts_ast_free_list() called each other, so
releasing the parse tree consumed one pair of thread stack frames
for every level of the tree.  sub_expr: '(' expr_lst ')' creates
one FTS_AST_SUBEXP_LIST per pair of parentheses, so a boolean
mode query with 2000 nested parentheses builds a chain of 4002
nodes, and fts_query_free() overflowed the thread stack
while freeing it.

fts_ast_visit() does not reach that depth, because
fts_ast_visit_sub_exp() limits the sub-expression nesting to
32 levels and returns DB_OUT_OF_MEMORY.
The parser has built the whole tree by then, and  it still has
to be freed.

fts_ast_node_print_recursive() recurses the same way. It is called
from fts_query_parse() when innodb_ft_enable_diag_print is enabled,
so it overflows the stack right after parsing, before the query is
executed.


Solution:
========
fts_ast_free_node(): Free the sub-tree with an explicit stack
instead of by recursion. The stack is threaded through the
next pointer of the very nodes that are about to be freed,
so it needs no extra memory and cannot fail to allocate.
A node is only pushed once it has been detached from the tree.
The children of a list are already chained to each other by next,
so a whole list is spliced onto the stack in one step.

fts_ast_free_list(): Removed, no longer needed.

fts_ast_node_print_recursive(): Stop at FTS_AST_PRINT_MAX_LEVEL and
print "..." instead of descending further.
Vladislav Vaintroub
MDEV-40878 avoid repeated parsing of PROXY headers

Do not parse multiple proxy headers. The protocol spec says the header is
at the beginning of a connection, so there could only be one.

According to example in the spec, in multi-layer scenarios, where several
proxies are involved between client and backend, the intermediate proxy
is supposed to be configured to replace the existing header. Thus multiple
headers are not expected.
Khaled Riyad
MDEV-41140 mariadb-server.postinst chown dereferences symlinks

The postinst, preinst, rpm postin and mysqld_safe scripts followed
symlinks when fixing ownership and permissions under /var/log/mysql
and /var/lib/mysql. Use -h and find -execdir, drop the rpm chmod, and
let mysqld_safe write as the mysql user, so symlinks there are no
longer dereferenced.

Behavior changes.
- symlinks inside these directories are no longer followed
- only the top level of /var/log/mysql is adjusted, not subdirectories
- the rpm scriptlet no longer runs chmod on the permission database
Vladislav Vaintroub
MDEV-40878 avoid repeated parsing of PROXY headers

Do not parse multiple proxy headers. The protocol spec says the header is
at the beginning of a connection, so there could only be one.

According to example in the spec, in multi-layer scenarios, where several
proxies are involved between client and backend, the intermediate proxy
is supposed to be configured to replace the existing header. Thus multiple
headers are not expected.
Georg Richter
Add cmake option RUN_UNSTABLE_TESTS for unit tests

Add the RUN_UNSTABLE_TESTS CMake option (default OFF) to exclude flaky
or timing-sensitive tests from default builds and CI runs.

Mark test_tls_openssl_err2 as unstable because it frequently times out
on GitHub Actions. Manual verification confirmed that OpenSSL correctly
returns x509_error=2 for the certificate provided by the fake server.
Dave Gosselin
MDEV-41746:  IN-subquery not allowed with OFFSET

Prevent OFFSET from appearing in IN, ALL, or ANY subqueries with
error ER_NOT_SUPPORTED_YET.  This mirrors how we prevent LIMIT
from appearing in similar queries.

Previously, OFFSET queries within IN-subqueries could return
wrong results if for example the OFFSET was past the end of the
table.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Oleksandr Byelkin
MDEV-39566 crash on a sorted scan of performance_schema.status_by_*

The bitmap of materialized rows in PFS_table_context was sized by the
live row count of the buffer container, which grows while a scan runs:
a sorted scan sizes it twice and asserted when the two sizes differed,
and set_item() could write past its end.  status_by_account used the
thread local key of status_by_host.  The allocation used the number of
bits in a word as its size in bytes.  m_last_item started at 0, so
set_item(0) did nothing and rnd_pos() dropped the first row.

Size the bitmap by the container maximum, which is fixed at startup;
give status_by_account its own key THR_PFS_SBA; allocate sizeof(ulong)
per word; start m_last_item at a sentinel.

Co-Authored-By: Claude Opus 5 <[email protected]>
Oleksandr Byelkin
MDEV-39566 crash on a sorted scan of performance_schema.status_by_*

The bitmap of materialized rows in PFS_table_context was sized by the
live row count of the buffer container, which grows while a scan runs:
a sorted scan sizes it twice and asserted when the two sizes differed,
and set_item() could write past its end.  status_by_account used the
thread local key of status_by_host.  The allocation used the number of
bits in a word as its size in bytes.  m_last_item started at 0, so
set_item(0) did nothing and rnd_pos() dropped the first row.

Size the bitmap by the container maximum, which is fixed at startup;
give status_by_account its own key THR_PFS_SBA; allocate sizeof(ulong)
per word; start m_last_item at a sentinel.

Co-Authored-By: Claude Opus 5 <[email protected]>
Aleksey Midenkov
Fix SSL test failures with GnuTLS client (11.4)

With WITH_SSL=bundled the server uses wolfSSL and Connector/C is
built with GnuTLS. The GnuTLS backend reports a CA-signed server
certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN,
which neither --ssl-fp nor password-based verification can override
(OpenSSL reports it as MARIADB_TLS_VERIFY_TRUST).

The fix:

  main.ssl_fp      skip unless the client uses OpenSSL or LibreSSL
  main.mysql      pass --ssl-ca to a GnuTLS client for the
                  --ssl-verify-server-cert check
  rpl.rpl_semi_sync_no_missed_ack_after_add_slave
                  include default_client.cnf, so check-testcase
                  connects with --disable-ssl-verify-server-cert
                  (also done in 10.11)
Alessandro Vetere
MDEV-41844 Test innodb.buf_pool_resize_pcur_restore is flaky

The procedure read_into_first_new_block() requires that the page of a
table is read into the first block that a buffer pool grow adds. While
history exists, the purge coordinator runs once per second. It reads
undo log pages, and purge_truncation_callback() reads the header page
of each rollback segment. On a slow builder, these reads can take the
first new block in all 5 attempts.

Stop purge for the duration of the test with FLUSH TABLES ... FOR
EXPORT on a separate connection. A read view does not stop these reads.
Remove the wait for purge between the two cases, because purge is
stopped.

purge_sys_t::stop() waits only for the purge coordinator. Runs of
purge_truncation_callback() that the coordinator submitted before can
still read pages after FLUSH TABLES ... FOR EXPORT returns. Add the
debug keyword purge_stop_wait_truncation, which makes
purge_sys_t::stop() also wait for these runs, and set it in the test.

Assisted-by: Claude:claude-opus-5-5
Vladislav Vaintroub
Merge 10.11 into 10.11-MDEV-40878
Oleksandr Byelkin
MDEV-35867 mariadb-check --repair does not repair sequences, only changes the status to OK

REPAIR of a sequence table with more or fewer than one row reported OK.
Now ha_sequence::repair() checks the row count after the engine repair
and reports the sequence as corrupt.

Also a failed table recreate in REPAIR was reported as
"Table is already up to date" (bool result taken as HA_ADMIN_ALREADY_DONE).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Thirunarayanan Balathandayuthapani
MDEV-41282 Recursion in InnoDB FTS AST causes stack-overflow (fts_ast_free_node/fts_ast_free_list)

Problem:
=======
fts_ast_free_node() and fts_ast_free_list() called each other, so
releasing the parse tree consumed one pair of thread stack frames
for every level of the tree.  sub_expr: '(' expr_lst ')' creates
one FTS_AST_SUBEXP_LIST per pair of parentheses, so a boolean
mode query with 2000 nested parentheses builds a chain of 4002
nodes, and fts_query_free() overflowed the thread stack
while freeing it.

fts_ast_visit() does not reach that depth, because
fts_ast_visit_sub_exp() limits the sub-expression nesting to
32 levels and returns DB_OUT_OF_MEMORY.
The parser has built the whole tree by then, and  it still has
to be freed.

Solution:
========
fts_ast_free_node(): Free the sub-tree with an explicit stack
instead of by recursion. The stack is threaded through the
next pointer of the very nodes that are about to be freed,
so it needs no extra memory and cannot fail to allocate.
A node is only pushed once it has been detached from the tree.
The children of a list are already chained to each other by next,
so a whole list is spliced onto the stack in one step.

fts_ast_free_list(): Removed, no longer needed.
Khaled Riyad
MDEV-41140 mariadb-server.postinst chown dereferences symlinks

The postinst, preinst, rpm postin and mysqld_safe scripts followed
symlinks when fixing ownership and permissions under /var/log/mysql
and /var/lib/mysql. Use -h and find -execdir, drop the rpm chmod, and
let mysqld_safe write as the mysql user, so symlinks there are no
longer dereferenced.

Behavior changes.
- symlinks inside these directories are no longer followed
- only the top level of /var/log/mysql is adjusted, not subdirectories
- the rpm scriptlet no longer runs chmod on the permission database
forkfun
MDEV-29510 ASAN errors upon updating a BLOB column twice in one UPDATE

UPDATE t SET a='x', b=a, a='foobarqux' makes b alias a's value buffer
(field_conv_memcpy() copies only the blob pointer while copy_blobs is
off). Storing a again frees that buffer and b dangles. So does
INSERT ... ON DUPLICATE KEY UPDATE.

fill_record(update=true) now stores a blob by value, unless the source
is a same-type blob column in engine memory, which nothing frees.

With copy_blobs set, Field_blob::store_field() copies a same-type blob
verbatim, skipping the charset check, and stores anything else through
store(), which checks the length. A trigger or UPDATE storing a longer
blob into a shorter one now fails or truncates with a warning, instead
of storing a wrapped length.

ODKU: VALUES() reads blob pointers saved in insert_values, which point
into Field_blob::value. Keep those buffers aside until the update is
done, so storing into a column does not overwrite them. With BEFORE
triggers, NOT NULL columns are stored through the field_to_fill()
clones, so keep those buffers too.

Assisted-by: Claude:claude-5.5-sonnet
Vladislav Vaintroub
Fixup be807b2d047: match GnuTLS only, not every non-OpenSSL client

Schannel on Windows is not OpenSSL either, but handles these cases.

Assisted-by: Claude:claude-sonnet-5-5
Aleksey Midenkov
Fix SSL test failures with GnuTLS client (11.4)

With WITH_SSL=bundled the server uses wolfSSL and Connector/C is
built with GnuTLS. The GnuTLS backend reports a CA-signed server
certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN,
which neither --ssl-fp nor password-based verification can override
(OpenSSL reports it as MARIADB_TLS_VERIFY_TRUST).

The fix:

  main.ssl_fp      skip unless the client uses OpenSSL or LibreSSL
  main.mysql      pass --ssl-ca to a GnuTLS client for the
                  --ssl-verify-server-cert check
  rpl.rpl_semi_sync_no_missed_ack_after_add_slave
                  include default_client.cnf, so check-testcase
                  connects with --disable-ssl-verify-server-cert
                  (also done in 10.11)