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
Alessandro Vetere
MDEV-42040 Recovery ignores failure to apply log to a new page

When the redo log initializes a page (INIT_PAGE), buf_read_recover()
does not read the page from the data file.
IORequest::fake_read_complete() builds the page from the log alone by
calling recv_recover_page().

If log_phys_t::apply() returns APPLIED_CORRUPTED, recv_recover_page()
evicts the page with buf_pool_t::corrupted_evict() and returns nullptr.
IORequest::fake_read_complete() ignored the nullptr and set no recovery
error flag. Thus srv_start() continued, a later checkpoint discarded the
log records of the evicted page, and the table stayed corrupted.

IORequest::fake_read_complete(): If recv_recover_page() returns nullptr,
call log_set_corrupt(). The page content comes only from the log, so
the failure is in the log. srv_start() now aborts with DB_CORRUPTION,
and the log is kept.

Assisted-by: Claude:claude-opus-5-5
Dave Gosselin
MDEV-42078:  Map macOS errno 63 in main.create_notembedded

Maps errno 63 to 36 in the output of the first CREATE TABLE in
main.create_notembedded, as main.symlink does.  That statement creates
a table whose file name is 255 bytes and expects ENAMETOOLONG in the
error, which is 36 on Linux and 63 on macOS.  The test has failed on
macOS since d0b279f1852 added it.

Assisted-By: Claude Opus 5.5 <[email protected]>
Georg Richter
MDEV-42145: Enable crl/crl_path for wolfssl/gnutls

- Fixed abort if a crl or crl_path was passed to a server which was built
  with WolfSSL
- Enable tests for all configurations
Vladislav Vaintroub
MDEV-42004: attach the connecting vio to the slave IO thread instead of signalling

Instead of pthread_kill(SIGUSR1), let the client tell the slave IO thread
about the vio as soon as it is created (slave_io_thread_attach_vio(), the
counterpart of the existing slave_io_thread_detach_vio()). THD::awake() then
shuts the socket down with vio_shutdown(), which wakes up the blocking wait
for the server greeting, on all platforms.
Andrei Elkin
MDEV-42004 STOP SLAVE waits for slave_net_timeout when master is unreachable

STOP SLAVE could take up to slave_net_timeout to stop the slave IO thread
when the primary accepts the connection but does not answer, e.g. when its
host is frozen or its packets are dropped.
The IO thread was blocked in a reconnect
  try_to_reconnect() -> safe_reconnect() -> connect_to_master() ->
  mysql_reconnect() -> mysql_real_connect()
and nothing could wake it up in the base of this patch, 11.4 at
c5272f132d3.

The poll() of the reconnect was interruptible before MDEV-32567 removed
the pthread_kill() of the slave thread in terminate_slave_thread()
(commit 013fc02a23e).

This commit restores it: pthread_kill() is back in terminate_slave_thread()
with SIGUSR1 and its handler, now installed in init_signals(). The original
loop there, which resends the signal, is preserved as well. The handler
records the signal in the thread-local slave_wakeup_signal, and
connect_to_master() reports it to the error log when log_warnings > 2:

  Slave I/O thread: reconnect to master '[email protected]:19000' was
  interrupted by signal 10 (User defined signal 1)

On Windows the pthread_kill() was compiled out before as well
(DONT_USE_THR_ALARM): there is no signal that interrupts a blocking socket
call of another thread. The stall there is not fixed.

Tested with rpl.rpl_semi_sync_stop_slave_unreachable_master.

The test simulates the server to refuse connections. It's important not to
crash the server as the kernel must still complete the
TCP handshake of a new connection, and let the IO thread to get into its
reconnect loop.
The test waits for that to most probably happen and then
runs STOP SLAVE, which normally (not on an overloaded server) must not wait
for slave_net_timeout.
A shut-down primary would not serve for that: its port is closed, so the
connect fails at once with "Connection refused", and the IO thread, which
then sleeps connect_retry in slave_sleep() (it checks io_slave_killed()),
stops promptly without this fix.

With --let $debug_test= 1 the test prints how long STOP SLAVE took. Measured
this way, it returned after 3.5 s before the fix and 1.0 s after, with
slave_net_timeout=3 and rpl_semi_sync_slave_kill_conn_timeout=1.
For a reliable run on BuildBot the time is not checked. The fix is proven
by grepping the slave's error log for the note above with
search_pattern_in_file.inc, which reports

  FOUND 1 /Slave I/O thread: reconnect to master .* was interrupted by signal [0-9]+/ in mysqld.2.err
Pekka Lampio
MDEV-38999: Galera - stale reads in explicit transactions

wsrep_must_sync_wait() skipped a statement's causal wait unconditionally
once a multi-statement transaction was open, regardless of which
wsrep_sync_wait bit was configured - so later statements could run
against a view no fresher than whatever BEGIN itself happened to check.
A timed-out wait's error also stayed sticky until commit/rollback,
breaking ROLLBACK itself.

Fix: only skip the wait once the transaction has made its first write or
locking read (SELECT ... FOR UPDATE/LOCK IN SHARE MODE, including via a
stored procedure CALL, autocommit statements, and UNION) - after that,
re-waiting risks a self-deadlock against the local applier. Clear a
timed-out wait's error immediately instead of leaving it sticky.

Tests: galera_MDEV-38999*.test cover the bitmask gap, the self-deadlock
risk, stored-procedure/UNION/autocommit locking reads, and the query
cache's independent wait path.

Assisted-by: Claude:claude-sonnet-5
Georgi (Joro) Kodinov
MDEV-42175: Do not compile 32-bit instructions for wolfSSL on 64bit platforms.

WolfSSL doesn't need some 32 bit code if it detects proper 64 bit mode.
Added a check for __uint128_t and made the 32 bit file conditional on this.
See https://github.com/wolfSSL/wolfssl/issues/11874 for details.
Georgi (Joro) Kodinov
MDEV-42175: Do not compile 32-bit instructions for wolfSSL on 64bit platforms.

WolfSSL doesn't need some 32 bit code if it detects proper 64 bit mode.
Added a check for __uint128_t and made the 32 bit file conditional on this.
See https://github.com/wolfSSL/wolfssl/issues/11874 for details.
Vladislav Vaintroub
MDEV-38741 mtr: do not suppress the reason of a client disconnect

The global suppressions of "Aborted connection", in mariadb-test-run.pl
and mtr_warnings.sql, hid the line that the client disconnect watcher
writes when it aborts a command: "Aborted connection N to db: 'x' user:
'u' host: 'h' (Client disconnected)". Nothing showed when the watcher
aborted a connection that it should have left alone. main.locale found
one, because its server log is in German and the English entry did not
match.

Make the two entries skip a line that ends in "(Client disconnected)".
Other aborted connections are suppressed as before.

The tests that drop a client on purpose accept the reason:
have_disconnect_watcher.inc, which the tests of the watcher include,
and dirty_close, loaddata, sp_notembedded, ssl_timeout, mysqltest,
innodb_bug38231, innodb.xa_recovery, mysql_client_test,
mysql_client_test_nonblock, mysql_client_test_comp,
rpl_semi_sync_shutdown_await_ack, spider/bugfix.mdev_35959 (a Spider
link that times out), main.mysqldump (mariadb-import can leave a LOAD DATA
running when it fails, MDEV-42164) and
mariabackup.nolock_ddl_during_backup_end (mariabackup ends in the middle
of a backup). The Connector/C tests of the unit suite close connections
on purpose, but cannot call mtr.add_suppression(), so suite.pm adds it
before each of them.

A replica closes its connection on purpose when it is stopped, in any
phase of its setup, also while the master runs one of its first
queries. rpl_init.inc accepts the reason for every server of the
replication tests, without writing it to the binlog. A binlog dump
thread logs its disconnect with another message, and only with
log_warnings=4.

Assisted-by: Claude:claude-sonnet-5-5
Jan Lindström
MDEV-41165: use I_S fast path with max_statement_time

Remove the max_statement_time fallback from is_simple_is_query().
The fast path now runs with a statement timer set.

In get_schema_tables_result(), add the debug sync point
i_s_fast_path_before_eof before EOF is sent. If the query was
killed or timed out after the WHERE condition was evaluated,
send the kill message instead of EOF.

Test changes:
- mdev_31342: rename the max_statement_time case, expect
  is_fast_path in EXPLAIN FORMAT=JSON, add the End of 13.2 tests
  marker.
- mdev_31342_kill (new): KILL QUERY and max_statement_time expiry
  after the scan, before EOF, plus a Handler_tmp_write check that
  the fast path is used.

Co-authored-by: Oleksandr Byelkin <[email protected]>
Vladislav Vaintroub
MDEV-42004: slave_net_timeout=60 in the test, for loaded hosts

STOP SLAVE has to return within half of slave_net_timeout, 30s now instead of 3s.
Vladislav Vaintroub
MDEV-42004 STOP SLAVE waits for slave_net_timeout when the primary is unreachable

STOP SLAVE could take up to slave_net_timeout to stop the slave IO thread
when the primary accepts the connection but does not answer, e.g. when its
host is frozen or its packets are dropped. The IO thread is blocked in
mysql_real_connect(), waiting for the server greeting, and THD::awake() could
not interrupt it: until the connect succeeds, the vio is not
THD::active_vio.

Let the client tell the owner of the connection about its vio. A new
MYSQL_OPT_VIO_CALLBACK (and MYSQL_OPT_VIO_CALLBACK_ARG, its first argument)
is called with the new vio as soon as it is created, and with NULL right before
it is deleted. It is kept in options.extension, so mysql_reconnect() carries it
over to its temporary MYSQL object.

The slave IO thread sets it up in connect_to_master(). The callback makes
the vio THD::active_vio, so STOP SLAVE shuts the socket down with
vio_shutdown(), which wakes up the blocked wait. If STOP SLAVE has already set
abort_slave, the vio is shut down right away. This works on all platforms, no
signals are needed.

The test does not need SIGSTOP and runs on Windows too. The "primary" is a
socket that listens and never accepts or answers. It fails without the fix
(STOP SLAVE waits for most of slave_net_timeout), and passes in about a
second with it.

The idea of the test, to freeze the primary and check that STOP SLAVE does not
wait for slave_net_timeout, is reused from Andrei Elkin's original patch for
this bug.

Co-authored-by: Andrei Elkin <[email protected]>
Yuchen Pei
MDEV-25848 bound range optimizer work for many ARRAY index points

With one range slot per ARRAY index, the number of points in a
SEL_ARG_ARRAY is no longer bounded by MAX_KEY, and a JSON_OVERLAPS or
JSON_CONTAINS constant with N elements cost (see the TODOs):

* N records_in_range() index dives, one per leaf, even when the
  estimate is never used;
* O(N^2) work in key_or_array(), which copied both point lists into a
  new SEL_ARG_ARRAY on every OR and deduplicated with a linear scan.

Now:

* key_or_array() appends the smaller point list to the larger
  SEL_ARG_ARRAY in place, or to a copy of it if it is shared
  (use_count > 0), without sorting or deduplicating.
* SEL_ARG_ARRAY::normalize() sorts and deduplicates the points once,
  when they are needed: estimates, quick select, optimizer trace.
* SEL_ARG_ARRAY::estimate() computes rows and cost lazily, on first
  use (key_and() or check_quick_select_array()). With
  eq_range_index_dive_limit or more points it dives on that many
  points spread over the sorted list and extrapolates.
* JSON_CONTAINS skips duplicate elements of the constant and uses at
  most eq_range_index_dive_limit distinct ones for the range, since
  each AND costs a dive and fewer conjuncts give a superset.

Points are now read in sorted order, so the order of rows from an
ARRAY index range scan may differ.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Dave Gosselin
MDEV-38643: ST_GeomFromText marks its SELECT with UNCACHEABLE_RAND

This patch removes the flag from ST_GeomFromText, ST_GeomFromWKB,
ST_GeomFromGeoJSON, ST_AsGeoJSON.

When called with one argument, these functions set UNCACHEABLE_RAND on
the enclosing SELECT.  In contrast, the forms with more arguments
never set that flag.

The flag was added in 2006 by commit 384407aaeb3, which moved the
function parsing out of sql_yacc.yy.  The prior grammar rules did not
set the flag for these, either.  The new code has the same form as the
code for ENCRYPT, which requires the UNCACHEABLE_RAND flag as its one
argument variant takes its salt from the clock.
Yuchen Pei
MDEV-25848 Allow "js IS NOT NULL AND <JSON_SARGABLE_PREDICATE on js>" to use range access
Vladislav Vaintroub
MDEV-42004 STOP SLAVE waits for slave_net_timeout when the primary is
unreachable

STOP SLAVE could take up to slave_net_timeout to stop the slave IO
thread when the primary accepts the connection but does not answer,
e.g. when its host is frozen or its packets are dropped. The IO thread
is blocked in mysql_real_connect(), waiting for the server greeting,
and THD::awake() could not interrupt it: until the connect succeeds,
the vio is not THD::active_vio.

Let the client tell the owner of the connection about its vio. A new
MYSQL_OPT_VIO_CALLBACK (and MYSQL_OPT_VIO_CALLBACK_ARG, its first
argument) is called with the new vio as soon as it is created, and with
NULL right before it is deleted. It is kept in options.extension, so
mysql_reconnect() carries it over to its temporary MYSQL object.

The slave IO thread sets it up in connect_to_master(). The callback
makes the vio THD::active_vio, so STOP SLAVE shuts the socket down with
vio_shutdown(), which wakes up the blocked wait. If STOP SLAVE has
already set abort_slave, the vio is shut down right away. This works on
all platforms, no signals are needed.

The test does not need SIGSTOP and runs on Windows too. The "primary"
is a socket that listens and never accepts or answers. It fails without
the fix (STOP SLAVE waits for most of slave_net_timeout), and passes in
about a second with it.

The idea of the test, to freeze the primary and check that STOP SLAVE
does not wait for slave_net_timeout, is reused from Andrei Elkin's
original patch for this bug.

Co-authored-by: Andrei Elkin <[email protected]>
Assisted-by: Claude:claude-sonnet-5-5
Vladislav Vaintroub
MDEV-38741 mariabackup: run the debug DDL as one statement

The debug thread of mariabackup that emulates a DDL sends several
statements in one query, and closes its connection as soon as the first
of them returned. The server used to run the rest. A server that aborts
the statement of a client that is gone does not, and
mariabackup.innodb_ddl_on_intermediate_table hangs, as the debug sync
signals the main thread waits for do not come. Run the statements in
one BEGIN NOT ATOMIC block, so that the client waits for all of them.
The ALTER of that test fails with a lock wait timeout on purpose, which
the handler of the block ignores, as the thread did before.

Assisted-by: Claude:claude-sonnet-5-5
Lawrin Novitsky
CONCPP-174 Integer getters were suboptimal.

The function checking if the value is inside type's range created
temporary string object and then it was destroyed. This range check was
run in most of cases.
The fix also removes this check in some cases - then the column type is
smaller interger and it's impossible for the value to be outside the
target range.
Yuchen Pei
MDEV-25848 bound range optimizer work for many ARRAY index points

With one range slot per ARRAY index, the number of points in a
SEL_ARG_ARRAY is no longer bounded by MAX_KEY, and a JSON_OVERLAPS or
JSON_CONTAINS constant with N elements cost (see the TODOs):

* N records_in_range() index dives, one per leaf, even when the
  estimate is never used;
* O(N^2) work in key_or_array(), which copied both point lists into a
  new SEL_ARG_ARRAY on every OR and deduplicated with a linear scan.

Now:

* key_or_array() appends the smaller point list to the larger
  SEL_ARG_ARRAY in place, or to a copy of it if it is shared
  (use_count > 0), without sorting or deduplicating.
* SEL_ARG_ARRAY::normalize() sorts and deduplicates the points once,
  when they are needed: estimates, quick select, optimizer trace.
* SEL_ARG_ARRAY::estimate() computes rows and cost lazily, on first
  use (key_and() or check_quick_select_array()). With
  eq_range_index_dive_limit or more points it dives on that many
  points spread over the sorted list and extrapolates.
* JSON_CONTAINS skips duplicate elements of the constant and uses at
  most eq_range_index_dive_limit distinct ones for the range, since
  each AND costs a dive and fewer conjuncts give a superset.

Points are now read in sorted order, so the order of rows from an
ARRAY index range scan may differ.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

MDEV-25848 deduplicate JSON_OVERLAPS/JSON_CONTAINS elements when parsing

Skip duplicate elements of the constant in json_get_range_elements(),
using a hash on the element's JSON text, instead of in
json_get_func_mm_tree() for JSON_CONTAINS only. Duplicates now never
become Items, SEL_ARG_ARRAY leaves or make_key() calls, for
JSON_OVERLAPS as well, and json_get_func_mm_tree() only counts the
distinct elements against eq_range_index_dive_limit.

The text includes the quotes of strings, so "1" and 1 are different.
Equal values with different text, such as 1 and 1.0, are still
deduplicated later by SEL_ARG_ARRAY::normalize().

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Pekka Lampio
MDEV-38999: Galera - stale reads in explicit transactions

wsrep_must_sync_wait() skipped a statement's causal wait unconditionally
once a multi-statement transaction was open, regardless of which
wsrep_sync_wait bit was configured - so later statements could run
against a view no fresher than whatever BEGIN itself happened to check.
A timed-out wait's error also stayed sticky until commit/rollback,
breaking ROLLBACK itself.

Fix: only skip the wait once the transaction has made its first write or
locking read (SELECT ... FOR UPDATE/LOCK IN SHARE MODE, including via a
stored procedure CALL, autocommit statements, and UNION) - after that,
re-waiting risks a self-deadlock against the local applier. Clear a
timed-out wait's error immediately instead of leaving it sticky.

Tests: galera_MDEV-38999*.test cover the bitmask gap, the self-deadlock
risk, stored-procedure/UNION/autocommit locking reads, and the query
cache's independent wait path.

Assisted-by Claude AI
Vladislav Vaintroub
MDEV-42004: pass the vio to the callback as void *

struct st_vio in a parameter list in sql_common.h is a C warning (error with
-Werror), as the type is not declared there.
Alessandro Vetere
MDEV-21725 Log page reorganization as the ranges by which records moved

btr_page_reorganize_low() logged the payload as one WRITE from the first
to the last changed byte. When the reorganization removes a gap near the
start of the page, it moves all the later records, and this WRITE covers
almost the whole page.

btr_page_reorganize_log_payload(): Log the payload with MEMMOVE for the
runs of records that only moved, and WRITE for the rest. The function
first copies the runs that moved towards the end of the page, in
descending order of destination. Then it copies the runs that moved
towards the start of the page, in ascending order of destination. In
each order, no copy changes the source of a later copy. If a copy of the
first order changed a part of a source, the function does not copy that
part. Instead, it logs with WRITE the bytes at the destination of that
part that differ from the old page. The function does not copy a run
that is shorter than 8 bytes. It also does not copy the shortest runs
that moved towards the end of the page when the working memory is full.
It logs the changed bytes of these runs with WRITE. The log format does
not change.

btr_page_reorganize_low(): Reserve a second scratch frame for the
working memory of btr_page_reorganize_log_payload().

page_copy_rec_list_end_no_locks(): Add the output parameter extra.

In all versions since the 10.5 redo log format, the recovery parser has
an error. For a same_page record that follows a MEMSET or MEMMOVE
record, it calculates an offset that is too low. It can then reject a
valid MEMMOVE whose source is below its destination as "Malformed log
record". Older servers and backup tools must still recover the log that
the new payload logging writes.

mtr_t::memmove(): Write the page identifier when the parser would
calculate a source below 8 (FIL_PAGE_PREV), which it rejects.
mtr_t::m_last_lag is the difference between the correct offset and the
offset that the parser calculates.

mtr_t::memset(), mtr_t::log_write(): Update mtr_t::m_last_lag.

recv_sys_t::parse_tail(): Add a FIXME for the parser error.

No new test: innodb.alter_copy and innodb.instant_alter_crash recover
page reorganizations. Without the mtr_t::memmove() change,
innodb.alter_copy, innodb.autoinc_persist, innodb.innodb-alter-tempfile,
innodb_fts.crash_recovery and innodb_zip.wl5522_debug_zip fail in
recovery.

innodb.index_lock_upgrade,on with 4k pages (Debug) writes 2,815,439
bytes of redo log instead of 3,293,565 (shutdown LSN minus startup LSN).

Assisted-by: Claude:claude-opus-5-5
Jan Lindström
MDEV-41926 : galera_mdev_31517 times out: mariadbd gets stuck

Wrong variable name in the configuration leads to
unireg_abort() during wsrep disconnect. However, if
Galera library has reached to IST receiver there was no
way to interrupt IST and mariadbd gets stuck in unireg_abort()
during wsrep disconnect. This issue has been fixed on Galera
library. For this test case we need to just verify that
Galera library version contains fix for SST/IST interrupt
i.e. at least 26.4.29.
forkfun
MDEV-24557 mariadb-dump: import MySQL 5.7+ users, grants, roles

--system=users/all now translates a MySQL 5.7+ source to MariaDB SQL.

- Privileges are mapped; those with no MariaDB equivalent are dropped
  with a "# WARNING". A partial revoke becomes DENY (13.1.1+), with a
  "# WARNING": an older server skips it.
- Translated GRANTs are gated 11.4. All grants are dumped last.
- WITH GRANT OPTION of a translated privilege is dropped. So is that of
  the static global grant, if a translated privilege has none: MariaDB
  has one option per level, and the account could grant it. A role with
  such a privilege is not considered for its members.
- CREATE USER clauses MariaDB lacks are dropped; an unsupported auth
  plugin locks the account. The hash is read as a string, not as 0x...
  (print_identified_with_as_hex), which MariaDB cannot parse.
- MySQL roles become MariaDB roles, renamed <user>_NNNN if the host is
  not '%' or the name is unavailable (taken, PUBLIC, NONE). Several
  default roles go into <user>_default_roles. A locked role account
  has none: it cannot log in.
- A mandatory role is granted to PUBLIC, with a "# WARNING": MariaDB
  activates it for every account, MySQL only where it is enabled.
- An unlocked role account (a hybrid) has its privileges on its role,
  which its members get, and on the account itself. The role is
  not its default role, so roles granted to the account stay inactive
  until enabled, as on MySQL. A locked role account has them on its
  role only.
- A comment end in a name is escaped in literals; in a GRANT or DENY the
  statement is emitted ungated, with a "# WARNING".

For a MariaDB source:
- The grants of a role also list those of the roles it includes: each
  statement is dumped once.

For every source:
- The /*!80001 CREATE ROLE, DROP ROLE, ALTER USER ... DEFAULT ROLE and
  /*!50701 DROP USER statements are gone: a dump no longer restores
  roles into MySQL.
- The dialect is detected in SQL, not from the version string.
- Roles are created WITH ADMIN mariadb_dump_import_role, so their order
  does not matter.
- DROP USER IF EXISTS is gated /*M!100103, and NO_AUTO_CREATE_USER is
  set while grants run. PUBLIC is not created as a role.

--insert-ignore now overrides --replace, with a warning; together they
gave an invalid REPLACE IGNORE.

Tests replay a dump captured from MySQL 26.7.0; recapture it after
changing the MySQL-source code (see mysql_users_setup.sql).

Assisted-By: Claude:claude-sonnet-5-5
rusher
Merge branch '3.4' into 3.4-perf
Georgi (Joro) Kodinov
MDEV-42175: Do not compile 32-bit instructions for wolfSSL on 64bit platforms.

WolfSSL doesn't need some 32 bit code if it detects proper 64 bit mode.
Added a check for __uint128_t and made the 32 bit file conditional on this.
See https://github.com/wolfSSL/wolfssl/issues/11874 for details.
Jan Lindström
MDEV-41165: use I_S fast path with max_statement_time

Remove the max_statement_time fallback from is_simple_is_query().
The fast path now runs with a statement timer set.

In get_schema_tables_result(), add the debug sync point
i_s_fast_path_before_eof before EOF is sent. If the query was
killed or timed out after the WHERE condition was evaluated,
send the kill message instead of EOF.

Test changes:
- mdev_31342: rename the max_statement_time case, expect
  is_fast_path in EXPLAIN FORMAT=JSON, add the End of 13.2 tests
  marker.
- mdev_31342_kill (new): KILL QUERY and max_statement_time expiry
  after the scan, before EOF, plus a Handler_tmp_write check that
  the fast path is used.

Co-authored-by: Oleksandr Byelkin <[email protected]>
rusher
[misc] Move the error-state test into CLEAR_CLIENT_ERROR and CLEAR_CLIENT_STMT_ERROR
Georgi (Joro) Kodinov
MDEV-42175: Do not compile 32-bit instructions for wolfSSL on 64bit platforms.

WolfSSL has different implementations of integer handling functions in sp_c32.c
and sp_c64.c.
Which one is used is determined by the SP_WORD_SIZE define.
SP_WORD_SIZE is auto-detected from indirect tests, like e.g. the presence
of __uint128_t (as determined by checking the HAVE___UINT128_T define).
Checking for this data type triggers SP_WORD_SIZE to be 64 on Mac (arm64)
and causes the code in sp_c32.c to be compiled out.
This also fixes the UBSAN warnings in it.

See https://github.com/wolfSSL/wolfssl/issues/11874 for details on these
warnings.

Fixed by adding a check for __uint128_t in wolfssl's cmake file and by
exporting the HAVE___UINT128_T define to all wolfssl related headers.
The latter is required since some of the headers used by the server
rely on this define.

Note that the code in sp_c64.c is supposedly more optimized for 64bit
platforms, so some modest performance improvement is also possible.
Alexey (Holyfoot) Botchkov
MDEV-36261 XMLTYPE: methods - step 1

Method functions added to the XMLTYPE.
  functions added here are:

  FUNCTION XMLTYPE.createNonSchemaBasedXML() RETURN XMLType
  FUNCTION XMLTYPE.getClobVal() RETURN LONGTEXT
  FUNCTION XMLTYPE.getNamespace() RETURN LONGTEXT
  FUNCTION XMLTYPE.isFragment() RETURN INTEGER
  FUNCTION XMLTYPE.getNumberVal() RETURN DOUBLE
  FUNCTION XMLTYPE.getStringVal() RETURN LONGTEXT
  FUNCTION XMLTYPE.getRootElement() RETURN LONGTEXT
Georgi (Joro) Kodinov
MDEV-42175: Do not compile 32-bit instructions for wolfSSL on 64bit platforms.

WolfSSL has different implementations of integer handling functions in sp_c32.c
and sp_c32.c.
Which one is used is determined by the SP_WORD_SIZE define.
SP_WORD_SIZE is auto-detected from indirect tests, like e.g. the presence
of __uint128_t (as determined by checking the HAVE___UINT128_T define).
Checking for this data type triggers SP_WORD_SIZE to be 64 on Mac (arm64)
and causes the code in sp_c32.c to be compiled out.
This also fixes the UBSAN warnings in it.

See https://github.com/wolfSSL/wolfssl/issues/11874 for details on these
warnings.

Fixed by adding a check for __uint128_t in wolfssl's cmake file and by
exporting the HAVE___UINT128_T define to all wolfssl related headers.
The latter is required since some of the headers used by the server
rely on this define.

Note that the code in sp_c64.c is supposedly more optimized for 64bit
platforms, so some modest performance improvement is also possible.
Hemant Dangi
MDEV-42122: check_port() must verify the listener is our own

Issue:
wait_for_listen() asks check_port() whether a process named
socat/nc/netcat is listening on the expected port, but passes no PID
to match against, so check_port() accepts any process with that name
anywhere on the system. On a busy host running many concurrent SSTs,
an unrelated process can transiently hold the same port number, and
wait_for_listen() then reports "ready" even though this invocation's
own listener never came up.

Solution:
When check_port() isn't given a specific PID to match, verify that a
candidate process found by name and port is this script's own
process or a descendant of it, rather than accepting any same-named
process. Existing callers that already pass a known PID are
unaffected.
Sergei Petrunia
MDEV-42044: I_S.OPTIMIZER_CONTEXT exposes rows, DDL and statistics ...

Optimizer Context has DDLs of used tables and VIEWs, table statistics,
and even captured table rows which include all, even the columns that
the query doesn't read.

The user running the query might not have access to some of this
information. Making it available in the optimizer context would create
an opportunity to bypass the security controls.

There is a similar issue in the Optimizer Trace. It is solved by not
producing optimizer trace if it would expose data that's not available
otherwise.

Piggy-back on the Optimizer Trace security checks and do the same:
disallow saving Optimizer Context if it can contain information that
the caller would not have access to.

In addition to Optimizer Trace's check, add
opt_ctx_can_read_all_columns() and check that when we're about to
dump a full table row into the optimizer context.
Thirunarayanan Balathandayuthapani
MDEV-39061 mariadb-backup compatible wrapper for BACKUP SERVER

This adds a shell script that lets users keep using their existing
mariadb-backup commands while the real work is done by the new
server-side BACKUP SERVER command. The goal is "drop-in": users
should not have to change their backup scripts.

mariadb-backup-server.sh : Understands the usual mariadb-backup
modes and translates each one.

mbstream-server.sh : lets streamed backups be unpacked by
pipelines that expect the mbstream CLI

mariadb-backup-pipe.sh is the stream sink that
BACKUP SERVER itself runs.

All three are documented in README.md.

--backup
========
Connects with the mariadb client and runs
"BACKUP SERVER TO '<dir>'".

Connection options (--user, --host, --port, --socket,
--defaults-file, ssl, ...) are passed through to the client.

--parallel=N becomes "<N+1> CONCURRENT": mariadb-backup
runs a dedicated log_copying_thread() besides its N data-copy
threads, while CONCURRENT counts every BACKUP SERVER worker.
The result is clamped to the 1..256 the parser accepts,
and to a minimum of 2.

After the backup it writes backup-prepare.cnf into the backup
directory, recording what --prepare needs later:
  - where mariadbd lives
  - InnoDB parameters (page size, data file path, undo tablespaces,
                      checksum algorithm, log file size)
  - If the server is encrypted then how to reload the
    encryption key plugin (the file_key_management variables),
    so an encrypted backup can be prepared without extra input.

--backup --stream
=================
Runs "BACKUP SERVER WITH 'pipe'".
The server only accepts a bare command name, which it resolves
n the PATH of the mariadbd process after prepending mariadb-backup-,
so uses the installed mariadb-backup-pipe instead.

mariadb-backup-pipe writes the tar into
.mariadb-backup-pipe-<stream>.tar, a named pipe the wrapper
created in the server @@datadir and is already draining to
its own stdout.

The backup therefore reaches the consumer as it is produced and
never lands on local disk. The wrapper appends backup-prepare.cnf
as a final tar afterwards; the server's tar carries no
end-of-archive marker, so that trailing archive supplies the
only one and the whole stream extracts with a plain "tar -x".
--parallel is ignored here, with a warning.

Four properties follow from how BACKUP SERVER streams,
all differing from mariadb-backup:
- local: the stream command runs inside the server,
so the wrapper must share its filesystem;
- fifo lives in @@datadir, because mariadb-backup-pipe resolves it
relative to the working directory of mariadbd, so --stream needs
write access there;
- tar only: any --stream=<format> yields tar;
- single-threaded: one worker, so no parallel read either.
--target-dir is optional in stream mode;

mbstream-server.sh maps the mbstream CLI onto a plain
"tar -x"/"tar -c", so existing "mbstream -x"/"-c" pipelines
keep working on the wrapper's stream.

mbstream-only flags (-p/--parallel, ...) are accepted and
ignored; any other unknown option is rejected.

Environment overrides:
MARIADB (client),
MARIADBD (the --prepare bootstrap server) and
TAR (the tar implementation, e.g. TAR=bsdtar) can each be overridden.

To run the bootstrap under rr, put it in MARIADBD and
let rr's own _RR_TRACE_DIR choose the trace location, e.g.
  _RR_TRACE_DIR=/dev/shm/rr MARIADBD='rr record mariadbd'

--prepare
=========
Starts "mariadbd --bootstrap" on the backup directory using
backup-prepare.cnf as its defaults file, replays the archived redo
log between the start and target LSN read from backup.cnf,
then builds a fresh ib_logfile0 so a normal server can start
on the directory.

mariadbd is taken from the path recorded in backup-prepare.cnf
if that binary exists, otherwise by searching
/libexec, /sbin, /bin and the configured install directories.

PATH is not searched; set MARIADBD to point elsewhere.
User --defaults-file/-extra-file and encryption options are
layered onto the bootstrap.

--copy-back / --move-back
=========================
Copy or move a prepared backup into the datadir. The datadir
is created if missing, a non-empty datadir is refused unless
--force-non-empty-directories is given, and a chown
reminder is printed.

If --aria-log-dir-path is given, the Aria logs (aria_log_control,
aria_log.*) are relocated into that directory.

Packaging
=========
The wrapper is not installed by default and never replaces the
real mariadb-backup / mbstream binaries.
1. cmake -DWITH_MARIABACKUP_WRAPPER=ON (default OFF) controls it.
2. When ON, the scripts install as /usr/bin/mariadb-backup-server,
/usr/bin/mbstream-server and /usr/bin/mariadb-backup-pipe, tagged
COMPONENT Backup so they ship in the mariadb-backup package.
mariadb-backup-pipe must end up in the PATH of the mariadbd
process, not merely in the PATH of whoever runs the wrapper.
3. RPM: nothing extra to do. the component handles it.
4. DEB: not wired. debian/rules uses --fail-missing and does not
enable the option, so the -server binaries are not listed.
To ship via DEB, make a paired change: add
-DWITH_MARIABACKUP_WRAPPER=ON in debian/rules and list all three of
usr/bin/mariadb-backup-server, usr/bin/mbstream-server and
usr/bin/mariadb-backup-pipe in debian/mariadb-backup.install together.
5. The real mariadb-backup/mbstream binaries and the
mariabackup symlink are left untouched; opt in via an alias or a
symlink early in PATH.

Limitations (not supported yet)
===============================
1) Incremental backup & prepare (--incremental-basedir,
  --incremental-dir, --apply-log-only)
2) --rollback-xa
3) Partial backup (--databases, --tables, --tables-file)
4) Output compression and encryption (--compress, --encrypt)
5) --export is accepted but only warns and runs a plain recovery
6) --extra-lsndir is ignored
7) --parallel is ignored with --stream
8) Windows: POSIX sh only, not installed on Windows

Behaviour differences from native mariadb-backup
================================================
- The wrapper needs the mariadb client on PATH for --backup;
--prepare needs mariadbd recorded in backup-prepare.cnf, in a
standard install directory, or named by MARIADBD
- BACKUP SERVER refuses an already-existing target directory
- BACKUP SERVER does copy the data file as raw pages without
checksum validation, so a corrupted table is not detected
at backup time
- --prepare only works on a wrapper-made backup: it
needs backup-prepare.cnf
- --stream is tar, not xbstream, local-only and single-threaded,
and needs write access to @@datadir for the fifo

Tests
=====
include/have_mariabackup_wrapper.inc redirects $XTRABACKUP to
mariadb-backup-server.sh and $XBSTREAM to mbstream-server.sh,
skipping when a wrapper or the mariadb client is unavailable.

include/have_mariabackup_combination.inc runs a test under both the
[CLIENT] mariadb-backup binary and the [SERVER] wrapper.
Vladislav Vaintroub
MDEV-38741 Abort the running statement when its client disconnects

The server notices that a client is gone only when it reads from or
writes to the socket. A statement that waits, for example for an InnoDB
row lock, keeps running, and its transaction keeps its locks.

Watch the client socket from the end of login until the connection ends
or the client sends COM_QUIT, with epoll (Linux), kqueue (BSD, macOS),
or on Windows with WSAEventSelect and an I/O completion port, and the
exit of the client process for a named pipe. When the client has gone,
the watcher sets DISCONNECT_SIGNALED in THD::disconnect_flags. If a
command that expects an answer is running, it is aborted with
KILL_CONNECTION. If the connection is idle, the next such command is
aborted when it starts. COM_QUIT and COM_STMT_CLOSE are not aborted, a
client can send them and then quit.

The events of a round are served by one scan of the connections, under
one read lock of the thread list. A scan for each event took the lock
for a long time: with 256 clients that connect and disconnect, 1300
scans per second cost 17% of the connection rate.

A command whose last reply is being sent is not aborted, there is
nothing left to interrupt. Protocol::end_statement() sets
DISCONNECT_UNINTERRUPTIBLE when it sends the last reply of a command:
an error, or a reply with no more results to follow. A read-only SELECT
sends its result early, from select_send::send_eof(), and the client
can quit while the server still cleans up. COM_STATISTICS and
COM_STMT_PREPARE write their replies themselves and set the flag before
they do. The lost connection is then logged as usual. The watcher and
the connection thread order their accesses with atomic read-modify-write
operations on the flags, no lock is taken for a command.

A connection that is already being killed is left alone. KILL
CONNECTION shuts the socket of its victim, which the watcher reports,
and a second awake of the dying thread would wait for it in
abort_current_cond_wait() for up to 2 seconds.

The socket is not shut down, the connection ends after the error is
sent, and the reason, "Client disconnected", is logged once. A
binlog dump thread logs "BINLOG DUMP client disconnected", and only
with log_warnings=4: a replica closes the connection on purpose when it
stops. A connection with the disconnect noted, idle or only finishing
its reply, shows that State in the processlist. Galera connections are
not aborted.

The global variable disconnect_watcher, ON by default, can be set OFF,
which also ends the watches that exist. It exists only where there is a
watcher: Linux, Windows, the BSDs and macOS, not the embedded server.

New tests: main.disconnect_*, sys_vars.disconnect_watcher_basic,
rpl.rpl_dump_thread_disconnect and mysql_client_test
test_disconnect_*. Some rpl and innodb tests are adjusted to pass with
the watcher ON and OFF.

Assisted-by: Claude:claude-sonnet-5-5
Vladislav Vaintroub
MDEV-42004: register the vio with a client callback, test on all platforms

Replace the hard-wired slave_io_thread_{attach,detach}_vio() functions with a
MYSQL_OPT_VIO_CALLBACK that the slave sets with mysql_options(). The client
calls it with the new vio and with NULL before the vio is deleted. The
callback lives in options.extension, so mysql_reconnect() carries it over to
its temporary MYSQL object, and embedded builds need no ifdefs.

The test no longer needs SIGSTOP: the "primary" is a listening socket that
never accepts, so it runs on Windows too (not_windows removed). It fails
without the fix (STOP SLAVE takes ~5s of slave_net_timeout=6) and passes in
about a second with it.
Pekka Lampio
MDEV-38999: Galera - stale reads in explicit transactions

wsrep_must_sync_wait() skipped a statement's causal wait unconditionally
once a multi-statement transaction was open, regardless of which
wsrep_sync_wait bit was configured - so later statements could run
against a view no fresher than whatever BEGIN itself happened to check.
A timed-out wait's error also stayed sticky until commit/rollback,
breaking ROLLBACK itself.

Fix: only skip the wait once the transaction has made its first write or
locking read (SELECT ... FOR UPDATE/LOCK IN SHARE MODE, including via a
stored procedure CALL, autocommit statements, and UNION) - after that,
re-waiting risks a self-deadlock against the local applier. Clear a
timed-out wait's error immediately instead of leaving it sticky.

Tests: galera_MDEV-38999*.test cover the bitmask gap, the self-deadlock
risk, stored-procedure/UNION/autocommit locking reads, and the query
cache's independent wait path.

Assisted-by Claude AI
Jan Lindström
MDEV-42140 require galera >= 26.4.29 in galera_wsrep_schema_detached

Add a galera library version check and the resulting .result line.
Requires a galera library with the MDEV-42140 IST allowlist fix.

Assisted-by: Claude:claude-4.6-sonnet