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
bsrikanth-mariadb
MDEV-42044: Check table privileges for the context recorder when trace is off
Vladislav Vaintroub
MDEV-38741 Abort the running statement when its client disconnects

A watcher thread subscribes to the OS notification that a client has
gone (e.g. TCP FIN or RST for a TCP socket, a gone client process for a
named pipe) and aborts the running statement like KILL CONNECTION does.
Controlled by the global variable disconnect_watcher. Details in
PR#6035.

Assisted-by: Claude:claude-sonnet-5-5
Jan Lindström
MDEV-31300 Suppress RESET SLAVE's Using_Gtid note across galera tests

RESET SLAVE/RESET SLAVE ALL emits a Note when it changes Using_Gtid,
and whether it does depends on the prior value, which can drift with
unrelated replication changes - galera_query_cache_invalidate,
galera_2_cluster and galera_gtid_2_cluster depend on it appearing.
Wrap every RESET SLAVE/RESET SLAVE ALL across the galera and
galera_3nodes suites in --disable_warnings/--enable_warnings, so no
test depends on that value.

Assisted-by: Claude:claude-4.6-sonnet
Pekka Lampio
MDEV-38999 followup: fix galera_sr.mysql-wsrep#215 regression

wsrep_must_sync_wait() now performs the causal wait on the first
real statement of an explicit transaction instead of skipping it as
soon as the transaction was merely BEGIN'd. mysql-wsrep#215
deliberately freezes node_1's local applier via a debug sync point
and then expects node_1's own first statement in the transaction to
proceed without waiting for that frozen apply - which the old,
buggy skip-on-BEGIN behaviour happened to allow, but the fix
correctly no longer does.

Disable wsrep_sync_wait for node_1's session before entering the
transaction, mirroring the same workaround node_1a's connection
already uses for the identical reason.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Thirunarayanan Balathandayuthapani
MDEV-42037 Assertion failure bpage->oldest_modification() when ALTER TABLE … DISCARD TABLESPACE races with the page cleaner

Problem:
=======
The page cleaner holds the latch of a dirty page while
buf_flush_space() has released buf_pool.mutex. DISCARD TABLESPACE
meanwhile runs buf_flush_remove_pages(), which removes the page from
buf_pool.flush_list without taking the page latch. When the cleaner
resumes, buf_flush_discard_page() asserts oldest_modification()

Solution:
========
buf_flush_discard_page(): remove the page from the flush list only if
oldest_modification() is nonzero. Always release the latch and free
the page, and return whether it was freed.
Elena Stepanova
MDEV-42198 Options from MTR opt files are added multiple times

Options from .opt files of included files were appended every time
the file was sourced, so they got repeated once per include path.
It caused unnecessary server restarts, and too long server command
lines lead to startup failures on Windows.

Now each file caches only its own .opt options plus an ordered list
of the files (itself and everything it sources) whose options apply,
each file listed once. The test's options are assembled from that list.
Options of included files still precede those of the including file.

Assisted-by: Claude:claude-opus-5-5
Rex Johnston
MDEV-39492 PQ: a worker's join buffers are allocated on the worker's thread

In a debug build main.parallel_query_join aborted in the worker THD's
destructor: status_var.local_memory_used was not zero, and safemalloc
reported the join buffer and its field descriptors as freed by a worker
thread but allocated by the query thread.

The manager built each worker's JOIN_CACHE in setup_worker_jointabs() and
called init() there, on the query thread. init() allocates the buffer with
my_malloc(MY_THREAD_SPECIFIC) and the field descriptors on the cache's
JOIN's THD, the worker's. A thread-specific allocation is charged to
current_thd at the time, the manager's THD, while the free -- the buffer in
pwt_worker::close_tables(), the descriptors when the worker THD's mem_root
is torn down -- is credited to the worker's THD on the worker's thread. Each
THD's count ended up off by the buffer in opposite directions, and ~THD
asserts on a non-zero count.

The cache object is still built by the manager, on the statement's
mem_root, with the previous tab chained and the trackers attached. init()
now runs at the start of pwt_worker::execute_and_handoff(), on the worker's
thread, in tab order, before anything is locked, so a failure has nothing
to undo and is reported as out of memory through the worker's error path.
The allocation and the free are then made by the same thread and charged
to the same THD.

This commit was prepared with Claude Code (Fable 5.1), which reproduced the
assertion under mtr, resolved the safemalloc allocation stacks to
JOIN_CACHE::init() called from setup_worker_jointabs(), moved the init()
call to the worker thread, and verified the 24 parallel_query tests pass in
both protocols on the debug build.
Jan Lindström
MDEV-31300 Suppress RESET SLAVE's Using_Gtid note across galera tests

RESET SLAVE/RESET SLAVE ALL emits a Note when it changes Using_Gtid,
and whether it does depends on the prior value, which can drift with
unrelated replication changes - galera_query_cache_invalidate,
galera_2_cluster and galera_gtid_2_cluster depend on it appearing.
Wrap every RESET SLAVE/RESET SLAVE ALL across the galera and
galera_3nodes suites in --disable_warnings/--enable_warnings, so no
test depends on that value.

Assisted-by: Claude:claude-4.6-sonnet
Elena Stepanova
MDEV-41085 Enable MTR tests on Windows: rpl suite

rpl.rpl_row_mysqlbinlog fails because apparently the client command
line on Windows cannot interpret the literal cp932 string which is
passed to it. Since the point of the test is not how the original
INSERT happens, but how it further works while replaying the binlog,
it should be acceptable to insert a hex-encoded value
Susil
MDEV-41446 rpl.rpl_fragment_row_event_main: wait for binlog checkpoint

The test failed in buildbot with a result content mismatch: in Test
Case 7 the Binlog_checkpoint event naming the current binlog was
listed after the CREATE TABLE events instead of before them.

That event is logged asynchronously, normally by the binlog background
thread, once the previous binlog has been checkpointed, so its position
among the first events of a freshly rotated binlog depends on timing.
Test Case 7 lists the events of the binlog opened by the FLUSH LOGS at
the end of the previous test case, without waiting for that event. The
other listings of this test wait for it, in rpl_fragment_row_event.inc,
with include/wait_for_binlog_checkpoint.inc.

Wait for the checkpoint event in the same way before the CREATE TABLE
in Test Case 7.

The listed checkpoint rows can also differ in a second way.
show_binlog_events.inc skips the first Binlog_checkpoint of a binlog,
which normally names the previous binlog. If a FLUSH LOGS runs before
the background thread has logged the checkpoint of the previous one,
that skipped event names an older binlog, and the checkpoint naming the
previous binlog is listed as an extra row. The cleanup at the end of
rpl_fragment_row_event.inc runs FLUSH LOGS shortly after the FLUSH LOGS
of its last test phase, without waiting in between. Wait for the
checkpoint before each of the three cleanup FLUSH LOGS (one per server).

The recorded result is unchanged.

Verified with the debug point
inject_binlog_background_thread_before_mark_xid_done, which holds back
one checkpoint event: with the event of the cleanup FLUSH LOGS held
back, only the wait in Test Case 7 prevents the diff reported in the
bug; with the event of the FLUSH LOGS before it held back, only the
cleanup waits prevent the extra row. Both changes together pass in both
cases.

The same ordering variance failed binlog.binlog_checkpoint, see
MDEV-29607.

Assisted-by: Claude:claude-sonnet-5-5
Vladislav Vaintroub
MDEV-30836 MTR hangs on Windows after warnings in the log at shutdown

Follow-up to the MDEV-30836 fix. With --force, parse_protocol()
returned 1 after a worker reported WARNINGS, so the manager went on
reading from the socket of that worker. A worker that was told to
exit with BYE sends WARNINGS and exits, and does not send anything
more.

On Windows Perl, non-blocking reads do not work, so the manager could
block in that read. It then never handled the results of the other
workers, and mtr hung after the last test.

Return 2 for such a worker, as for the other cases where the worker
needs no response, to continue with the next ready socket. The closed
socket is handled later, when it becomes readable.

A worker that was not told to exit also sends WARNINGS, before it
restarts servers or after a test with side effects, and then goes on
to send TESTRESULT. Keep reading from it, as before. The manager
remembers the workers it said BYE to.

Assisted-by: Claude:claude-sonnet-5-5
Jan Lindström
MDEV-42139 fix spurious wakeup in gu_debug_sync_wait()

In galera_3nodes.galera_join_with_cc_X this let a waiter on the
"process_primary_configuration" sync point disappear from
wsrep_debug_sync_waiters between a wait_condition.inc poll and the
test's own follow-up SELECT, producing an empty result instead of the
point name.

Test now requires Galera library 26.4.29 where fix for
spurious wakeup in gu_debug_sync_wait() is.
bsrikanth-mariadb
MDEV-42044: Fix Optimizer Context privilege checks

Follow-up to the previous MDEV-42044 commit:

* opt_trace_disable_if_no_security_context_access() returned early when
  the optimizer trace was not started, so a context recorded through
  DEFINER routines, triggers or views was never marked as restricted.
  Mark the recorder before that return.
* Skip the access checks when built with NO_EMBEDDED_ACCESS_CHECKS.
* Factor the repeated "missing privilege" code in opt_trace.cc into
  helpers.

Tests: assert the "Insufficient privileges" output, and add cases for
column-level grants, an unexecuted function, a DEFINER trigger,
optimizer_trace=ON, and a privileged user who still gets a full context.
Alexey Yurchenko
MDEV-41851 register cache manager with SAVEPOINT handler list

MDEV-41851 happens because by the time SAVEPOINT is called there
exists no connection cache manager yet and it does not care to
create one. As a result the cache manger is lazily created later
but is missing from the SAVEPOINT's handler list and thus is not
fired on ROLLBACK TO SAVEPOINT keeping the event in the cache
which in turn is replicated on subsequent COMMIT and applied on
the replicas.
Make sure to create cache manager in wsrep_register_binlog_handler()
if it does not yet exist.
Vladislav Vaintroub
MDEV-42049 MTR server-cert.pem has no DNS SAN, fails on OpenSSL 4.1

OpenSSL 4.1 no longer matches a host name against the subject CN when
the certificate has no DNS subjectAltName. Re-sign server-cert.pem with
subjectAltName=DNS:localhost, and add it to generate-ssl-certs.sh.

main.ssl_7937, main.ssl_system_ca and rpl.rpl_ssl1 fail with
OpenSSL 4.1 without this change.

The SHA1 fingerprint changes. main.ssl_fp (11.4+) must be updated when
merging up: F1:D0:08:AF:A1:D2:F4:15:79:B4:39:06:41:F4:20:96:F1:90:A9:65
-> AE:F0:29:15:F1:9E:A0:A0:69:FB:83:20:B9:30:E3:DE:2F:25:2C:37

Assisted-by: Claude:claude-sonnet-5-5
bsrikanth-mariadb
MDEV-42044: Create the context recorder before the trace privilege checks
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 with mtr.add_suppression(),
details in PR#6035.

Assisted-by: Claude:claude-sonnet-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.
Alexander Barkov
MDEV-39563 Implement UPDATE ... RETURNING ... INTO

Adding support for UPDATE .. RETURNING .. INTO queries.

For example:

  UPDATE t1 SET a=10,b=20 RETURNING a,b INTO va,vb;
  UPDATE t1 SET a=10,b=20 RETURNING a,b INTO @a,@b;

Limitations:
1. These types of queries:
  - REPLACE .. RETURNING .. INTO
  - DELETE .. RETURNING .. INTO
  - INSERT .. RETURNING .. INTO
  do not work - they return an error.
  They will be implemented separately, when needed.

2. UPDATE..RETURNING..INTO with --binlog_format=statement is not allowed
  and an error is raised.

3. Using OLD_VALUE(col) inside UPDATE..RETURNING..INTO is not allowed
  and an error is raised.

4. Multi-table updates, as well as single table updates with a subquery
  to the same table in WHERE (which get converted to multi-table) do
  not work and an error is raised.

5. UPDATE IGNORE .. RETURNING .. INTO is not supported for storage engines
  that can send updates later (Spider), because it is not known if the row
  was rejected. ER_NOT_SUPPORTED_YET is raised.

Notes:

1. ANALYZE and EXPLAIN
  Both
    ANALYZE UPDATE .. RETURNING .. INTO ..
    EXPLAIN UPDATE .. RETURNING .. INTO ..
  return this error:
    'RETURNING..INTO' is not allowed in this context

2. Behavior on no data and on multiple rows

  Only the rows that were actually changed are processed. A row that matches
  the WHERE condition but needs no update is not changed, so it is not
  returned by plain RETURNING either.

  Situation                    | RETURNING        | RETURNING .. INTO
  -----------------------------+------------------+-----------------------------
  Empty table, WHERE matches  | empty set        | Warning ER_SP_FETCH_NO_DATA,
  nothing, WHERE 1=0, LIMIT 0  |                  | target is not changed

  One row matches, needs no    | empty set        | Warning ER_SP_FETCH_NO_DATA,
  update                      |                  | target is not changed

  Several rows match, none    | empty set        | Warning ER_SP_FETCH_NO_DATA,
  needs an update              |                  | target is not changed
                              |                  | (no ER_TOO_MANY_ROWS)

  One row matches and is      | that row        | Target is assigned
  changed                      |                  |

  Several rows match, exactly  | that row        | Target is assigned from
  one changes                  |                  | that row

  Two or more rows change      | all changed rows | ER_TOO_MANY_ROWS at the 2nd
                              |                  | changed row (not updated)

  Notes:
  - The warning is never an error: not in the strict mode, not with
    sql_mode='', not with IGNORE. The INTO targets keep their old values.
    In stored routines the warning activates NOT FOUND handlers.
  - This is the same for all storage engines, including those that quickly
    know the table is empty and use a degenerated plan (e.g. MyISAM).
  - After ER_TOO_MANY_ROWS, transactional engines roll back the statement,
    non-transactional engines keep the rows updated before the error
    (the second changed row is not updated).
  - The targets can be user variables, SP variables, ROW variables
    and ROW fields.

3. Behavior on VIEW with CHECK OPTION

  The "too many rows" check is done after the view's CHECK OPTION check.
  With UPDATE IGNORE, a row rejected by WITH CHECK OPTION is skipped
  (with a warning) and does not count as an updated row, so
  UPDATE IGNORE .. RETURNING .. INTO does not raise ER_TOO_MANY_ROWS
  if only one row is actually updated.

4. Behavior of UPDATE IGNORE .. RETURNING .. INTO

  With IGNORE, a row rejected by the storage engine (a duplicate key,
  no partition for the new values, a foreign key violation) is not changed,
  so it is not counted as a changed row, in the same way as for plain
  UPDATE IGNORE .. RETURNING. The engine decides about this in
  ha_update_row(), so the check for the second changed row is done after it:
  - Transactional engines: ER_TOO_MANY_ROWS rolls back the statement.
  - Non-transactional engines: the second row is updated back (including
    its BLOB values) before ER_TOO_MANY_ROWS is raised. Both updates are
    written to the binary log.
  Without IGNORE the check is done before the second row is updated.

Helper changes:

1. The grammar in analyze_stmt_command was changed to have
  LEX::analyze_stmt set to true earlier, so
  LEX::set_returning_into_result() already knows if this
  is an ANALYZE statement.

2. The Sql_cmd_update constructor is now called earlier in the grammar,
  to be able to call Sql_cmd_update::set_with_old_value_items()
  in the SET and RETURNING clauses.

3. Sql_cmd_dml::lex is now set during the constructor time.
  It makes things easier:
  - Sql_cmd_update::returns_result_set() needs the lex.
  - Sql_cmd_delete::orig_multitable and Sql_cmd_update::orig_multitable
    are not needed any more.
    They were used only in Sql_cmd_delete::sql_command_code() and
    Sql_cmd_update::sql_command_code().
    Sql_cmd_dml::sql_command_code() now returns lex->sql_command.
    The overrides Sql_cmd_delete::sql_command_code() and
    Sql_cmd_update::sql_command_code() were removed.

4. A new virtual method handler::update_may_be_deferred() tells if
  ha_update_row() can return success for a row that the engine rejects
  later. It is overridden in Spider and in ha_partition.

This commit also fixes bugs found during testing:
- MDEV-41262 ER_TOO_MANY_ROWS should be checked after CHECK OPTION in view
  while Update Returning Into
- MDEV-41265 SELECT/ UPDATE RETURNING INTO a single row-field fails with
  ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, even though the column count matches
  This bug was also fixed in 12.3.4.
- MDEV-41260 Misleading message text "uses a LIMIT clause" after Update
  Returning Into
- MDEV-42212 UPDATE ... RETURNING ... INTO raises ER_TOO_MANY_ROWS on InnoDB
  when the second found row needs no update
- MDEV-42156 UPDATE IGNORE ... RETURNING ... INTO fails with
  ER_TOO_MANY_ROWS when the second row is skipped by IGNORE (duplicate key)
Alexander Barkov
MDEV-39563 Implement UPDATE ... RETURNING ... INTO

Adding support for UPDATE .. RETURNING .. INTO queries.

For example:

  UPDATE t1 SET a=10,b=20 RETURNING a,b INTO va,vb;
  UPDATE t1 SET a=10,b=20 RETURNING a,b INTO @a,@b;

Limitations:
1. These types of queries:
  - REPLACE .. RETURNING .. INTO
  - DELETE .. RETURNING .. INTO
  - INSERT .. RETURNING .. INTO
  do not work - they return an error.
  They will be implemented separately, when needed.

2. UPDATE..RETURNING..INTO with --binlog_format=statement is not allowed
  and an error is raised.

3. Using OLD_VALUE(col) inside UPDATE..RETURNING..INTO is not allowed
  and an error is raised.

4. Multi-table updates, as well as single table updates with a subquery
  to the same table in WHERE (which get converted to multi-table) do
  not work and an error is raised.

5. A row that looks changeable but is rejected by the engine (IGNORE with
  a duplicate key, no partition or foreign key violation) is still counted
  as found, so ER_TOO_MANY_ROWS can be raised while plain RETURNING
  returns only one row. Engines with batched updates (Spider) may return
  a row that was not changed. See MDEV-42156.

Notes:

1. ANALYZE and EXPLAIN
  Both
    ANALYZE UPDATE .. RETURNING .. INTO ..
    EXPLAIN UPDATE .. RETURNING .. INTO ..
  return this error:
    'RETURNING..INTO' is not allowed in this context

2. Behavior on no data and on multiple rows

  Only the rows that were actually changed are processed. A row that matches
  the WHERE condition but needs no update is not changed, so it is not
  returned by plain RETURNING either.

  Situation                    | RETURNING        | RETURNING .. INTO
  -----------------------------+------------------+-----------------------------
  Empty table, WHERE matches  | empty set        | Warning ER_SP_FETCH_NO_DATA,
  nothing, WHERE 1=0, LIMIT 0  |                  | target is not changed

  One row matches, needs no    | empty set        | Warning ER_SP_FETCH_NO_DATA,
  update                      |                  | target is not changed

  Several rows match, none    | empty set        | Warning ER_SP_FETCH_NO_DATA,
  needs an update              |                  | target is not changed
                              |                  | (no ER_TOO_MANY_ROWS)

  One row matches and is      | that row        | Target is assigned
  changed                      |                  |

  Several rows match, exactly  | that row        | Target is assigned from
  one changes                  |                  | that row. But see
                              |                  | Limitation 5.

  Two or more rows change      | all changed rows | ER_TOO_MANY_ROWS at the 2nd
                              |                  | changed row (not updated)

  Notes:
  - The warning is never an error: not in the strict mode, not with
    sql_mode='', not with IGNORE. The INTO targets keep their old values.
    In stored routines the warning activates NOT FOUND handlers.
  - This is the same for all storage engines, including those that quickly
    know the table is empty and use a degenerated plan (e.g. MyISAM).
  - After ER_TOO_MANY_ROWS, transactional engines roll back the statement,
    non-transactional engines keep the rows updated before the error.
  - The targets can be user variables, SP variables, ROW variables
    and ROW fields.

3. Behavior on VIEW with CHECK OPTION

  The "too many rows" check is done after the view's CHECK OPTION check.
  With UPDATE IGNORE, a row rejected by WITH CHECK OPTION is skipped
  (with a warning) and does not count as an updated row, so
  UPDATE IGNORE .. RETURNING .. INTO does not raise ER_TOO_MANY_ROWS
  if only one row is actually updated.

Helper changes:

1. The grammar in analyze_stmt_command was changed to have
  LEX::analyze_stmt set to true earlier, so
  LEX::set_returning_into_result() already knows if this
  is an ANALYZE statement.

2. The Sql_cmd_update constructor is now called earlier in the grammar,
  to be able to call Sql_cmd_update::set_with_old_value_items()
  in the SET and RETURNING clauses.

3. Sql_cmd_dml::lex is now set during the constructor time.
  It makes things easier:
  - Sql_cmd_update::returns_result_set() needs the lex.
  - Sql_cmd_delete::orig_multitable and Sql_cmd_update::orig_multitable
    are not needed any more.
    They were used only in Sql_cmd_delete::sql_command_code() and
    Sql_cmd_update::sql_command_code().
    Sql_cmd_dml::sql_command_code() now returns lex->sql_command.
    The overrides Sql_cmd_delete::sql_command_code() and
    Sql_cmd_update::sql_command_code() were removed.

This commit also fixes bugs found during testing:
- MDEV-41262 ER_TOO_MANY_ROWS should be checked after CHECK OPTION in view
  while Update Returning Into
- MDEV-41265 SELECT/ UPDATE RETURNING INTO a single row-field fails with
  ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, even though the column count matches
  This bug was also fixed in 12.3.4.
- MDEV-41260 Misleading message text "uses a LIMIT clause" after Update
  Returning Into
- MDEV-42212 UPDATE ... RETURNING ... INTO raises ER_TOO_MANY_ROWS on InnoDB
  when the second found row needs no update
Hemant Dangi
MDEV-42091: --prepare must not trust plugin_dir from backup-my.cnf

Issue:
backup-my.cnf is part of the backup/transfer directory and can arrive over
an untrusted channel (e.g. a Galera SST stream). --prepare honored its
plugin_dir value as-is, letting whoever supplied the backup redirect
plugin loading to a directory of their choosing.

Solution:
Pass the joiner's own, locally-resolved --plugin-dir on the --prepare
command line: it wins over whatever backup-my.cnf says, regardless of
content, unless the user already chose one explicitly via
inno-apply-opts, which takes priority as a deliberate local choice.
Resolve it by asking the joiner's own mariadbd, which is config- and
compiled-default-aware, falling back to a plain config lookup if that's
unavailable. Add a regression test driving the real SST joiner script
directly: deliver a backup stream whose backup-my.cnf claims an
attacker-chosen plugin_dir, and confirm that directory is never
referenced.
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.
Elena Stepanova
MDEV-42200 main.mysqlbinlog_stmt_compressed depends on previous tests
xnervwang
MDEV-41940 sys.ps_setup_reload_saved() leaves session sql_log_bin disabled after an error

sys.ps_setup_reload_saved() saves @@sql_log_bin and sets sql_log_bin =
0, but restores it only at the end of the procedure. On an error, its
EXIT HANDLER raises SQLSTATE 90001 without restoring sql_log_bin,
leaving the calling session with sql_log_bin = 0. Keep the saved value
in a local variable, as the fix for MDEV-42005 does, and restore it in
the handler when sql_log_bin differs from it. A caller that may not
set sql_log_bin fails at SET sql_log_bin = 0; the handler then leaves
sql_log_bin alone, so that caller still gets error 90001.
Thirunarayanan Balathandayuthapani
MDEV-41336 CHECK TABLE EXTENDED crashes with innodb_force_recovery=3

Problem:
=========
  After a restart where purge has not run (When
innodb_force_recovery=3), purge_sys.head and purge_sys.tail are both
unset (trx_no=0). trx_lists_init_at_db_start() calls
purge_sys.clone_oldest_view<true>(), which clamped end_view to that
0, so end_view.m_low_limit_id became 0 and changes_visible()
returned false for every transaction id. end_view therefore
claimed that no history had been purged, although undo log records
purged before the restart may already have been freed and reused.

CHECK TABLE EXTENDED relies on end_view to decide whether an old
version's undo log record is still available. It followed the roll
pointer of a purged transaction into a reused undo page and
trx_undo_rec_get_pars() hit the assertion

Solution:
========
In purge_sys_t::clone_oldest_view<true>(), clamp end_view only if
purge has a known position (head.trx_no/tail.trx_no is nonzero).
Otherwise keep the oldest view as is, so that the undo log records
that purge is allowed to remove are reported as
DB_MISSING_HISTORY rather than being read.
Andreas Schnederle-Wagner
MDEV-41751 A FULLTEXT index added later misses rows when the first one was added to an empty table

When ALTER TABLE rebuilds a table with a hidden FTS_DOC_ID column, as
when adding the first FULLTEXT index or rebuilding a table that has
one, prepare_inplace_alter_table_dict() sets DICT_TF2_FTS_ADD_DOC_ID on
the new table, so that row_merge_build_indexes() assigns new FTS_DOC_ID
values; it clears the flag when it is done. Since MDEV-23805,
inplace_alter_table() skips that phase when the table is empty, so the
flag stayed set in the cached table definition until the table was
loaded again, for example after a restart. A FULLTEXT index added
before that without a rebuild got new document IDs instead of the
FTS_DOC_ID of the rows, and searches on it did not find the rows that
existed when it was created.

Do not set the flag when inplace_alter_table() skips that phase, that
is, when ha_alter_info->mdl_exclusive_after_prepare is set.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
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.
xnervwang
MDEV-42005 sys.diagnostics(), sys.ps_trace_thread() and sys.ps_trace_statement_digest() leave session sql_log_bin disabled

sys.diagnostics(), sys.ps_trace_thread(), and
sys.ps_trace_statement_digest() save @@sql_log_bin in @log_bin before
disabling binary logging, but calls to ps_setup_save(),
ps_setup_reload_saved(), and statement_performance_analyzer() overwrite
that saved value with 0. The trace procedures hit this when
in_auto_setup or in_auto_enable is TRUE; diagnostics() hits it whenever
the PERFORMANCE_SCHEMA engine is listed as supported, including with
performance_schema=OFF.

The three procedures now save the value in a local v_log_bin variable.
The new sysschema.pr_ps_trace_thread test and added cases in
sysschema.pr_diagnostics and sysschema.pr_ps_trace_statement_digest
check @@sql_log_bin before and after a successful call.
Mohammad Tafzeel Shams
MDEV-37467: InnoDB Instant ALTER TABLE is not crash safe

The hidden metadata record of instant ALTER TABLE was not written
crash-safely, and recovery could fail to roll it back. These are
independent problems.

First, the metadata record may include externally stored BLOB
metadata. The existing BLOB storage path in
btr_store_big_rec_extern_fields() writes the clustered index record
first, with zero BLOB pointers, and only fills in the BLOB pointers
afterwards. If the server is killed after the mini-transaction that
wrote the (incomplete) metadata record was durably committed, but
before the BLOB pointers were written, the table could become
inaccessible on recovery.

Make metadata BLOB storage crash-safe by writing the BLOB pages and
computing their pointers before the metadata record itself is
inserted or updated, so that the record is always written with
complete BLOB pointers. If the server is killed before the metadata
record is written, the already-written BLOB pages are merely
orphaned, which is safe.

Second, trx_undo_report_row_operation() writes the undo log record in
a mini-transaction of its own, which is committed before the
mini-transaction that writes the metadata record. Because
innobase_instant_try() had already updated SYS_COLUMNS and SYS_TABLES
in earlier mini-transactions, a kill in between left a durable undo
log record for the table while the metadata record was unchanged. On
recovery, trx_resurrect_table_locks() would then load the table
definition before the incomplete transaction was rolled back. The
data dictionary described the table as it would be after the
operation, while the metadata record still described it as it was
before, and btr_cur_instant_init() failed on that disagreement.

Write the undo log record of the metadata record in the same
mini-transaction that inserts or updates the record, so that the two
cannot be separated by a crash: until that mini-transaction is
committed, neither of them is durable.

An undo log record is never split between pages. If the DEFAULT
values of the columns being added are large enough that the undo log
record for updating the metadata record would not fit on one page,
innobase_instant_try() would fail. Determine this before the operation
starts, so that it can be performed by another algorithm instead.

Third, the table definition that recovery loads need not correspond to
the metadata record. dict_load_table_one() reads the committed version
of the SYS_TABLES record, and escalates to READ UNCOMMITTED only when
it finds a SYS_COLUMNS record that was written by a transaction that is
still active. The number of SYS_COLUMNS records that dict_load_columns()
reads is derived from SYS_TABLES.N_COLS, which was read from the
committed version. The record of a column that the operation appended is
located after that many records, so it is never read and the operation
goes unnoticed. Only an instant ALTER TABLE that merely appends columns
can escape this way: ADD COLUMN ... FIRST, DROP COLUMN and column
reordering rewrite the SYS_COLUMNS records of already existing columns.

Load the committed table definition first, and the uncommitted one only
if btr_cur_instant_init() reports that the committed definition does not
describe the metadata record. Reading the uncommitted definition
unconditionally would be wrong in the opposite case: if the operation
had not updated the metadata record yet, the definition would describe
columns that the record does not comprise, and btr_cur_instant_init()
would request the default value of a column that does not have one.

Fourth, the rollback writes a metadata record that comprises fewer
fields than the table definition describes, because
btr_cur_trim_alter_metadata() shortens it to the number of fields that
it comprised before the operation. That number determines the size of
the null flag bitmap, and hence the position of the array of field
lengths. rec_init_offsets_comp_ordinary() derives it from the record,
while the two functions that write the record derived it from the table
definition and asserted that the two agree.

- btr_store_big_rec_metadata():
  New function to store the off-page columns of a metadata record
  ahead of time. Each BLOB page is allocated and linked in its own
  mini-transaction, and the resulting BLOB pointers are written
  directly into the (heap-resident) index entry. On failure, it frees
  any pages it already allocated and resets the pointers to zero.

- btr_free_big_rec_metadata():
  New helper to free the BLOB pages written by
  btr_store_big_rec_metadata() and reset the entry's BLOB pointers
  to zero, used both on failure inside that function and by its
  callers when the metadata record ends up not being written.

- row_ins_clust_index_entry_low():
  For a metadata entry that needs external storage, convert it to a
  big record and call btr_store_big_rec_metadata() (with
  log_free_check() allowed, since no latches are held yet) before
  inserting the record. On failure, free the metadata BLOBs and
  convert the entry back.

- btr_cur_pessimistic_update():
  When updating a metadata record that requires external storage,
  call btr_store_big_rec_metadata() (without log_free_check(),
  since index and page latches are held) before modifying the record,
  and free the temporary big_rec vector via btr_free_big_rec_metadata()
  or dtuple_big_rec_free() on the various failure/success paths.

- btr_cur_optimistic_insert():
  Remove the special-cased jump to convert_big_rec for metadata
  entries, since their BLOBs are now always stored ahead of time by
  the caller; assert that a metadata entry never needs external
  storage at this point.

- innobase_instant_try():
  Since btr_cur_pessimistic_update() now stores metadata BLOBs
  before updating the record, big_rec is always NULL here; assert
  this instead of calling btr_store_big_rec_extern_fields().

- trx_undo_report_row_operation():
  New parameter caller_mtr. If it is specified, the undo log record
  is written in that mini-transaction, which is never committed or
  restarted here. An undo log page is added within the same
  mini-transaction if the record does not fit on the current one. A
  temporary table never uses the caller's mini-transaction, because
  that would require changing its logging mode. All other callers
  pass NULL and are unaffected.
  Encapsulate the parameters that describe the row change
  (clust_entry, update, cmpl_info, rec, offsets) in the new type
  trx_undo_row_op, which of the fields are set depends on the
  operation, which the type documents.

- btr_cur_ins_lock_and_undo(), btr_cur_upd_lock_and_undo():
  For an instant ALTER TABLE metadata record, pass the
  mini-transaction that is going to insert or modify the record.

- trx_undo_max_rec_size():
  New function to determine the maximum size of an undo log record,
  that is, the space available on an empty undo log page.

- ha_innobase::check_if_supported_inplace_alter():
  Refuse ALGORITHM=INSTANT if the metadata record already exists and
  the undo log record for updating it would exceed
  trx_undo_max_rec_size(). trx_undo_page_report_modify() stores the
  DEFAULT value of each column that is being added in that record in
  full, inline. No such limit applies when the metadata record is
  being inserted, because trx_undo_page_report_insert() writes
  TRX_UNDO_INSERT_METADATA and no field data.

- dict_load_table_one():
  Load the committed table definition first, and the uncommitted one
  only if btr_cur_instant_init() reports that the committed definition
  does not describe the clustered index metadata record.
  dict_load_columns() cannot detect this, because the number of
  SYS_COLUMNS records that it reads is derived from SYS_TABLES.N_COLS,
  and a column that the operation appended is located after that many
  records. A table that an uncommitted transaction is rebuilding is
  excluded, because the committed definition is the one that
  corresponds to its clustered index.

- btr_cur_instant_init(), btr_cur_instant_init_low():
  Determine the number of fields of the metadata record in the same way
  as rec_init_offsets_comp_ordinary() does, and refuse the table if it
  disagrees with the table definition. rec_get_offsets() would otherwise
  request the default value of a column that does not have one. New
  parameter quiet for a caller that is going to try another table
  definition, so that an attempt which is not the final one is not
  reported. Mark the table as unreadable on these failures, like the
  other ones in that function do, because dict_load_table_one() asserts
  that a readable table is not corrupted.

- dict_sys_tables_rec_read():
  Store the fields that are read in the new type dict_sys_tables_rec,
  instead of in separate output parameters. A caller that does not want
  a delete-marked record to be reported as not found used to indicate
  that by specifying trx_id as nullptr; that is now the parameter
  skip_deleted.

- trx_undo_add_page():
  Correct the documented restriction on the mini-transaction of the
  caller.

- rec_get_converted_size_comp_prefix_low(),
  rec_convert_dtuple_to_rec_comp():
  For a record that includes a metadata BLOB, determine the number of
  nullable fields from the tuple, by way of
  dict_index_t::get_n_nullable(), and not from
  dict_index_t::n_nullable. This is what
  rec_init_offsets_comp_ordinary() does, and it is equivalent for a
  tuple that comprises all fields of the index. Relax the assertions
  that required the tuple to comprise all of them.

- Added test in innodb.instant_alter and innodb.instant_alter_crash
  to test normal working of INSTANT ALTER, crash safety and full table.
Hemant Dangi
MDEV-41388: Avoid causal-wait timeout in galera.MDEV-34117

Issue: After re-enabling wsrep_on, the test's local session-variable
checks (SET/SELECT @@wsrep_trx_fragment_unit/size) pay the suite's
default causal-read wait (wsrep_sync_wait=15). On loaded/slow CI
builders (aarch64-debian-12, s390x-ubuntu-2204) this occasionally
exceeds the 90s causal_read_timeout and fails with
ER_LOCK_WAIT_TIMEOUT, even though none of these checks depend on
cross-node consistency.

Solution: Disable wsrep_sync_wait for this narrow window of
local-only checks, matching the existing on/off pattern used in
galera_concurrent_test.inc and galera_mdev38999_cleanup.inc, and
restore it before the later statements that do read data replicated
from node_1.

Assisted-by: Claude:claude-sonnet-5
Elena Stepanova
MDEV-41085 Enable MTR tests on Windows: rpl suite

rpl.rpl_read_old_relay_log_info fails because the test overrrides
relay-log.info with the Linux-style ./slave-relay-bin.000001,
while Windows uses the format with backslashes, .\slave-relay-bin.000001
bsrikanth-mariadb
MDEV-42186: Info leak with optimizer_replay_context

Replaying a context for a query on a view made the server push
warnings naming the underlying tables, their indexes and the view's
hidden range constants, even if the user could not read those tables.

On the first use of the replay, check that the invoker can read all
columns of every base table in the statement. If any table fails the
check, drop the context, so nothing is replayed and no warnings are
produced.
Hemant Dangi
MDEV-41158: authenticate the mariabackup SST backup-data stream too

Issue:
The joiner's per-transfer secret was only generated for
ssl-mode=VERIFY_*, and checked only on the small GTID stage: the
backup-data stage itself was accepted unauthenticated, letting any
TCP peer reaching the SST port supply a backup --prepare then runs.

Solution:
Generate the secret unconditionally and require it on the backup-data
stream too, built in lockstep with the existing encrypt/decompress/
progress wrapping so the check can't be silently skipped by it. Add
sst-mariabackup-allow-unauthenticated-donor for rolling upgrades,
failing closed on invalid values; VERIFY_*'s own pre-existing secret
check is unaffected by it. Add a regression test covering the
authenticated pipeline with that wrapping active.
bsrikanth-mariadb
MDEV-42186: Info leak with optimizer_replay_context

Replaying a context for a query on a view made the server push
warnings naming the underlying tables, their indexes and the view's
hidden range constants, even if the user could not read those tables.

On the first use of the replay, check that the invoker can read all
columns of every base table in the statement. If any table fails the
check, drop the context, so nothing is replayed and no warnings are
produced.
Sergei Petrunia
Fixup: opt_ctx_can_read_all_columns() is not used for VIEWs.
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
Elena Stepanova
MDEV-42202 perfschema.relaylog fails when run after other replication tests

The test checks file I/O instrumentation accumulated since server
startup, so it relied on getting freshly started servers. With
duplicate options removed, mtr may now reuse servers left by
a previous replication test, and the test sees binary/relay log
files and statistics from it.

Restart both servers at the beginning of the test, removing
binary and relay logs while the servers are down. RESET MASTER
and RESET SLAVE are not sufficient, as performance schema keeps
instances of files deleted by them, and a restart opens a new
binary log anyway.

Assisted-by: Claude:claude-opus-5-5
Elena Stepanova
MDEV-41085 Enable MTR tests on Windows: rpl suite

rpl.rpl_change_master_long_channel_name fails on Windows because it
expects a 252-character name (base name, excluding the path) to be
valid; on Windows the whole path is limited to 260 characters, so
252-character name already fails
Jan Lindström
MDEV-42141 tolerate ER_NO_SUCH_TABLE in GCF-1018B's reap

wsrep_sync_wait=0 lets node_2's DELETE run before node_1's CREATE
TABLE replicates, so the first iteration of the test's 500-iteration
INSERT/DELETE loop can legitimately race a not-yet-existing t1. The
--error list on node_2's reap did not accept ER_NO_SUCH_TABLE, even
though it already tolerates other non-deterministic races (lock wait,
deadlock, duplicate key) for the same reason, matching the pattern
used for the same race in GCF-1060 (MDEV-41923).