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
Rion Bora
MDEV-40839 SET members from the 9th on lost on a pushed-down SELECT

Type_handler_set::make_table_field() built the Field_set with
get_enum_pack_length(), the ENUM rule (1 byte below 256 values), so
a SET with more than 8 members got a 1-byte field in the temporary
table of a select handler (used by the DuckDB engine and by FederatedX
with federated_pushdown=1) and every member from the 9th on was cut
off. Use get_set_pack_length(), as the other Type_handler_set
functions already do.

Tests: duckdb.set_wide_members and federated.federatedx_set_pushdown.
Nikita Malyavin
MDEV-41238 mysqltest: add PS_bind_long command

mysqltest gets a PS_bind_long command. It binds like PS_bind, but
sends every value with mysql_stmt_send_long_data() before each
PS_execute, so a test can reach a parameter in LONG_DATA_VALUE state.
Aleksey Midenkov
MDEV-40821 Wrong result after DELETE HISTORY or PORTION OF (10.11)

The parser assigned versioning conditions of DELETE HISTORY ... BEFORE
SYSTEM_TIME and period conditions of DELETE ... FOR PORTION OF to the
table pointed by last_table(). When the BEFORE SYSTEM_TIME or FOR
PORTION OF expression references another table (e.g. via a subquery or
a sequence function), last_table() is already switched to that table,
and the DELETE target gets no conditions.

DELETE HISTORY then deletes current rows permanently instead of
history, keeps the history it had to purge, and is checked for DELETE
privilege instead of DELETE HISTORY. DELETE HISTORY from a
non-versioned table is not rejected with ER_VERS_NOT_VERSIONED.
DELETE ... FOR PORTION OF deletes all rows of the table, ignoring the
period.

The fix assigns the conditions to the TABLE_LIST returned by
delete_single_table, i.e. the DELETE target itself, regardless of
tables added later in the statement.

DBUG_ASSERT in TABLE::vers_switch_partition() is removed. It checked
delete_history on last_table() and assumed no other table is opened
for write by DELETE HISTORY, which is false for the underlying table
of a view or a table locked by SELECT ... FOR UPDATE in the history
point. The DELETE HISTORY target is already skipped there by its own
delete_history check.
Nikita Malyavin
MDEV-41238 Bound parameters prevent condition pushdown into a grouped view, while CAST enables it

Item_param::deep_copy() returned NULL, and every rewrite that copies a
condition gives up on what it cannot copy. A conjunct holding a
prepared statement parameter was therefore left out of:
- pushdown into derived tables and views, including UNION branches
  and conditions on a derived table column whose expression holds a
  parameter;
- pushdown from HAVING to WHERE, for the part extracted from an OR;
- pushdown into a materialized IN subquery;
- split materialization, which then found no split key;
- the UPPER(col) IN (...) rewrite, which has skipped such conjuncts
  since MDEV-40006.
When the derived table groups by an expression with a parameter, the
condition was pushed into its HAVING instead of its WHERE.

CAST(? AS ...) worked around this only by accident. Before the
pushdown, constant propagation can replace a constant expression on
one side of = with a literal. A bare parameter already counts as a
basic constant, so propagation leaves it as it is. A client whose
charset differs from the column's got the pushdown by a similar
accident: the charset conversion replaces the parameter with a
literal.

Item_param::shallow_copy() now copies a parameter that holds a value,
NULL included, and deep_copy() calls it, as in other leaf items. Every
such copy is made while optimizing during EXECUTE, and the next
EXECUTE makes a new one, so a copy always carries the value bound for
the EXECUTE that made it. A copy that outlived its EXECUTE would keep
an old value and point into a string buffer that the next binding may
free, so shallow_copy() asserts that it does not allocate on the
statement's arena.

The copy is not added to m_clones. m_clones keeps the parameter's
copies in CTE definitions updated with each new value for the whole
life of the statement, while this copy lives for one execution.

An unbound parameter, DEFAULT and IGNORE still have no copy.
Marko Mäkelä
fixup! 883556d1a77c1c0004d95f0b8ffdc66de2a029f8
Oleksandr Byelkin
Fix use-after-poison on BINLOG with a Query event in EXECUTE IMMEDIATE

Query_log_event::do_apply_event() freed thd->mem_root, which inside a
BINLOG statement also freed the statement's own memory, e.g. Items of
EXECUTE IMMEDIATE freed later in THD::cleanup_after_query().

Free thd->mem_root only in replication/wsrep appliers, as
Rows_log_event::do_apply_event() does.

Reviewed by [email protected]
Sergei Golubchik
check for truncated packets when reading bound parameter values

and clear the error flag on correct values
Rucha Deodhar
MDEV-33843: Server crashes by stack-overflow with UPDATEXML

Analysis:
The stack size if insufficient and there is no stack overrun check.

Fix:
Add stack overrun check.
Khaled Riyad
MDEV-41470 Server crashes in check_grant / delete_precheck on 2nd execution of SP

When a procedure changes a view that calls a stored function, the
tables of that function are added to the statement's table list for
prelocking. From the second call on, they are already in the list
when the privilege precheck runs. `check_one_table_access()` took the
first of them for a table of the view, and the check then walked past
the end of the list and crashed.

Stop in `check_one_table_access()` when no tables owned by the
statement are left. The prelocking tables are checked when their
routines run.
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.
Raghunandan Bhat
MDEV-40836: Window function in ORDER BY split twice by split_sum_func()

Problem:
  A window function inside an ORDER BY expression was split twice by
  `split_sum_func()` first in `setup_order()`, then again in
  `JOIN::prepare()`. Each split adds the item to `ref_pointer_array`,
  which resulted in overflow.

  The split in `setup_order()` was added by MDEV-28094 (8c34eab) to fix
  a crash in -
    SELECT EXISTS (SELECT 1 ORDER BY 1+sum(2) OVER ());

  `check_and_do_in_subquery_rewrites()` dropped the ORDER BY of that
  subquery, so `JOIN::prepare()` never split it. But its window function
  was still registered with the select and processed, causing the crash.

Fix:
  - When check_and_do_in_subquery_rewrites() drops the ORDER BY, also
    remove its window functions from `SELECT_LEX::window_funcs`.
  - Remove the window function split from `setup_order()`, so it is
    done only once, in `JOIN::prepare()`.
Oleksandr Byelkin
Fix use-after-poison on BINLOG with a Query event in EXECUTE IMMEDIATE

Query_log_event::do_apply_event() freed thd->mem_root, which inside a
BINLOG statement also freed the statement's own memory, e.g. Items of
EXECUTE IMMEDIATE freed later in THD::cleanup_after_query().

Free thd->mem_root only in replication/wsrep appliers, as
Rows_log_event::do_apply_event() does.

Reviewed by [email protected]
bsrikanth-mariadb
MDEV-41293: FederatedX: connection state after a net_read_timeout

Problem:
When reading the reply of the remote server times out, the client
library compiled into the server returns without closing the connection
and without setting a client error. FederatedX took the raw
ER_NET_READ_INTERRUPTED for an error of the remote server and went on
using a connection that still had the reply of the failed statement to
arrive. As a result:
* the next statement on that connection failed in various ways, either
  with ER_QUERY_ON_FOREIGN_DATA_SOURCE ("Server has gone away") or with
  an error packet that mysqltest took for a malformed packet;
* inside a transaction, the following statements continued on a new
  remote session in autocommit mode, so they were committed on the
  remote server one by one even though the local transaction was later
  rolled back. The savepoints of the lost session were also still
  remembered by FederatedX.
The same happened when the connection was lost while reading the reply.

Fix:
* After a timeout FederatedX closes the connection, so that the next
  statement opens a new one. The client still gets the error of the
  timeout, ER_NET_READ_INTERRUPTED.
* Whenever the connection is gone after a failed statement, timeout or
  not, the state of the lost session (autocommit mode, savepoints) is
  forgotten and the local transaction is marked to be rolled back, so a
  new connection starts the transaction again. This includes the case
  where the connection is lost while SET AUTOCOMMIT=0 is sent for the
  first statement of the transaction. The closed connection is also
  freed, which was leaked before.
* Errors of the client library are reported as
  ER_QUERY_ON_FOREIGN_DATA_SOURCE by ha_federatedx::info() as well, the
  same way as by the pushed down multi-table UPDATE/DELETE.
* The error state of ha_federatedx, read by info(), is initialized.

Test: federatedx_pushdown_upd_del covers the timeout of a pushed down
multi-table UPDATE and DELETE and of reading a result, the statements
after it, the same inside a transaction, a connection killed in the
middle of a statement, a connection lost while SET AUTOCOMMIT=0 is sent
(also followed by a disconnect and a transaction in another session),
client library errors in info(), and that an error of the remote server
which merely has the code of ER_NET_READ_INTERRUPTED is not taken for a
timeout.
bsrikanth-mariadb
MDEV-41243, MDEV-41273 Don't freeze mem_root after engine pushdown

When a statement is pushed down to an engine, the once-per-statement
part of the optimization (e.g. the first_cond_optimization part of
JOIN::optimize(), or the whole of JOIN::optimize() for a pushed down
UNION) is skipped. Re-executing the same prepared statement or stored
routine without pushdown then allocated from a mem_root already marked
ROOT_FLAG_READ_ONLY, hitting an assertion in alloc_root().

Add LEX::dont_freeze_mem_root, set by the pushdown_handler and
derived_handler constructors so it covers every engine implementing
them. Prepared_statement::execute_loop(), sp_head::execute() (through
sp_head::dont_freeze_mem_root) and the SP instruction reparse path no
longer freeze the mem_root of such statements. The flag is only
declared and used in PROTECT_STATEMENT_MEMROOT builds.

The flag is per execution for prepared statements:
Prepared_statement::execute_loop() clears it after each execution, so
the mem_root is frozen again after the first later execution that is
not pushed down. For a stored routine the instruction's LEX keeps the
flag, so once one instruction has been pushed down the routine's
mem_root stays unfrozen, even if later executions are not pushed down,
unless the routine is re-parsed into a new LEX.

Add tests for prepared SELECT, UNION, UPDATE and DELETE, prepared
EXPLAIN of a pushed UNION, derived tables, stored procedures,
functions, triggers, cursors and metadata-invalidation reparse, with
pushdown switched on and off. Most prepared statement and routine
tests check the statements received by the remote server, or EXPLAIN,
to verify that pushdown actually happened.
Oleksandr Byelkin
MDEV-41652 SIGFPE in get_next_time/Event_queue_element::compute_next_execution_time

get_next_time() took the interval value as int, so converting it to
seconds or months could overflow, e.g. 268435456 HOUR wrapped to 0
and the months branch divided by zero.

Pass the interval as longlong and reject month counts that do not
fit INTERVAL::month (32-bit on Windows).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Oleksandr Byelkin
MDEV-39306 fix race in versioning.rpl_row

The slave created table t before the master's previous DROP TABLE t
was replicated. Sync the slave after the drops.

Reviewed by [email protected]
Oleksandr Byelkin
MDEV-39306 fix race in versioning.rpl_row

The slave created table t before the master's previous DROP TABLE t
was replicated. Sync the slave after the drops.

Reviewed by [email protected]
Marko Mäkelä
MDEV-14992/MDEV-38362/MDEV-39092 BACKUP SERVER

The following SQL statements will be introduced:

BACKUP SERVER TO '/path/to/directory' [ 1 CONCURRENT ];
BACKUP SERVER WITH [ 1 CONCURRENT ] 'command';

In place of the 1, any positive number of threads may be specified.
For the first variant, '/path/to' must exist and '/path/to/directory'
must not exist; that is where the backup will be written to.

For BACKUP SERVER WITH, the string mariadb-backup-
will be prepended to the specified command and quoted.
Path separators or quotes are not allowed in command.
We expect the mariadb-backup-command to be in the
search PATH of the mariadbd process.
For now, we distribute no such script or program;
the user has to write one, something like this:
exec zstdmt|ssh [email protected] "exec cat > $1.tar.zstd"
The standard input of that command will be in a format compatible with
GNU tar --format=oldgnu (and also BSD tar variants that are also part of
Microsoft Windows and Apple macOS). The command is expected to optionally
compress and encrypt the stream and redirect it to a file on a local or
a remote server. The BACKUP SERVER WITH will append an additional argument,
a positive base-ten number in ASCII, starting with 1, to identify the
current thread. In this way, there can be multiple concurrent streams.
The InnoDB write-ahead log will be streamed near the end, because
the stream format requires the file sizes to be declared upfront.

In BACKUP SERVER TO ... 2 CONCURRENT or more, one thread will be
responsible for copying the InnoDB write-ahead log from the beginning
of the backup, running InnoDB_backup::log_track(). Other files will be
copied by other threads.

Note: In single-threaded BACKUP SERVER TO, the parameter
innodb_log_recovery_start that is written out to backup.cnf is
STRICTLY NECESSARY TO AVOID CORRUPTION during recovery! By default,
InnoDB crash recovery starts from the latest available log
checkpoint. However, for restoring a backup, recovery must start from
the checkpoint that was the latest when the backup was
started. Starting recovery from a possible later checkpoint will
result in a corrupted database!

The backup or the first stream will contain a file backup.cnf, which
includes parameters needed for restoring the backup. Currently,
these are innodb_log_recovery_start and innodb_log_recovery_target.
If innodb_log_recovery_target>0, InnoDB will be in read-only mode,
not allowing any writes to persistent files other than via the log
application.

To restore a streaming backup made with BACKUP SERVER WITH, an empty
directory needs to be created and all streams be extracted there using
the standard tar utility of the operating system, optionally after
undoing any encryption or compression that had been added by the
backup command. Then, the backup is prepared or MariaDB server started
up on the extracted directory, similar to as if the BACKUP SERVER TO
statement had been used.

The following will be implemented separately:

MDEV-39061 mariadb-backup compatible wrapper script for BACKUP SERVER
MDEV-40163 Partial backup and restore
MDEV-39091 Back up ENGINE=RocksDB
MDEV-40333 Concurrent DDL for Aria tables in BACKUP SERVER

The implementation introduces a basic multi-threaded driver
Sql_cmd_backup, storage engine interfaces, and basic copying of the
storage engines InnoDB, Aria, MyISAM, MERGE (MyISAM), Archive, CSV.

backup_target: A structured data type to represent a target directory.
On Microsoft Windows, we must use directory paths because there is
no variant of CopyFileEx() that would work on file handles.

backup_sink: Wraps a per-thread output stream as well as storage
engine specific context. The member "id" identifies the thread,
between 0 and CONCURRENT-1.

backup_context: Process-wide BACKUP SERVER context.
Handles the directory traversal and copying of
files for built-in storage engines that do not
implement this backup interface.

backup_target_stage: Wrap backup_context.

backup_target_stage::step(),
backup_context::step(): Process a file
from a directory scan, or by invoking
handlerton::backup_step().

handlerton::backup_file(): Check if a file should be
included in the backup. Implemented for ENGINE=Aria
in maria_backup_file().

handlerton::backup_start(), handlerton::backup_end(): Invoked at the
start or end of a backup phase, in the thread that executes a
BACKUP SERVER statement.

handlerton::backup_step(): A backup step that can be invoked from
multiple threads concurrently, between the execution of the corresponding
handlerton::backup_start() and handlerton::backup_end() of the same
phase.

copy_entire_file(): A file copying service for POSIX systems.

copy_file_range_try(): A wrapper for Linux copy_file_range(2), which
may fail with EOPNOTSUPP or EXDEV and thus require a fallback to
backup::copy().

backup::copy(): A partial or sparse file-copying service.  On other
platforms than FreeBSD or Microsoft Windows, there are shortcut
alternatives to this. Note: On Linux we never invoke sendfile(2) for
copying between files, because can be much slower than the
alternatives.

backup::copy_or_stream(): Copy or stream a file.

backup_stream_append_plain(): A wrapper of backup::append(), which is
the streaming equivalent of backup::copy().

backup_stream_zeropad(): Zero-pad the last tar block if needed.

backup_stream_append_async(): A variant of backup_stream_append_plain()
where the source file region is guaranteed to be immutable after the
call returns. Zero-copy Linux sendfile(2) is inherently risky for copying
data files that may be modified in place, because it could introduce
a race condition between a page write that runs concurrently with a
child process that is reading the data from the pipe. This could be
improved with io_uring later.

pread_write(): Allocate a buffer of up to 4 MiB.
This is the "slow path" of copying or streaming files.

maria_backup_start(): Copy ENGINE=Aria log files.
(FIXME: currently single-threaded and race condition prone!)

InnoDB_backup::init(): Wait for a possible previous BACKUP SERVER
operation to reach the very end of InnoDB_backup::context::cleanup()
so that the context can be safely reused.

InnoDB_backup::queue: Collection of tablespace IDs and payload sizes
at the start of the backup, and the log_sys.first_lsn of log files
that have to be included in the backup. If any data file is created or
extended while the backup is executing, we must have the corresponding
write-ahead-log entries that we are copying since the latest
checkpoint that was completed when the backup started. If any
tablespaces are deleted during the backup, we may or may not copy
them, and the application of a FILE_DELETE record will remove them.
Similarly, applying FILE_RENAME or FILE_CREATE records will rename or
create files during recovery as needed.

InnoDB_backup::context::tracked: Log file queue for the dedicated
log-copying task InnoDB_backup::log_track().

innodb_backup_log_tracking(): Determine if log-tracking backup is
active, which blocks concurrent changes of innodb_log_file_buffering
and innodb_log_file_write_through.

log_sys.backup: Whether BACKUP SERVER is in progress. The purpose of this
is to make BACKUP SERVER prevent the concurrent execution of
SET GLOBAL innodb_log_archive=OFF or SET GLOBAL innodb_log_file_size
when innodb_log_archive=OFF.

log_sys.archived_checkpoint: Keep track of the earliest available
checkpoint, corresponding to log_sys.archived_lsn. This reflects
SET GLOBAL innodb_log_recovery_start (which is settable now), for
incremental backup.

fil_system.have_all_spaces: Whether all tablespace metadata is guaranteed
to be known. To speed up startup, InnoDB does not normally open
all tablespace files.

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

fil_space_t::backup_end: The first page number that is not being backed up
(by default 0, to indicate that no backup is in progress).

fil_space_t::BACKUP_BATCH_SIZE: The number of preceding pages that will be
covered by fil_space_t::backup_end. This is the unit of "page range locking"
during InnoDB backup.

fil_node_t::backup_name: A snapshot of the file name, sampled in
InnoDB_backup::init(). For backing up any files that were created before
the backup start checkpoint LSN, these names will be written to the backup.
On restore, the files will be renamed or deleted as needed, by
applying FILE_RENAME or FILE_DELETE records.

fil_node_t::rename(), fil_node_t::set_backup_name(),
fil_node_t::get_backup_name(), fil_node_t::~fil_node_t(),
fil_node_t::clear_backup_name(): Deal with fil_node_t::backup_name.

buf_page_t::write_fix_try(), buf_page_t::write_unfix_try(): Try to set
or unset a fake "write fix" on a page, to prevent concurrent flush()
during a backup batch. The atomic operations may run concurrently with
set_reinit() and set_freed(). The fake "write fix" does not prevent
any concurrent read or write of the page data in the buffer pool; it
only blocks writes to the underlying data file.

buf_page_t::flush(): Atomically test and set write fix, and
skip the operation if the fake "write fix" was set.

buf_page_t::set_freed(), buf_page_t::set_reinit(): Employ a
compare-and-exchange loop to accommodate for the "write fix".

innodb_backup_batch_wait(): Look up any pages that we are about to
back up. For any dirty pages, invoke buf_page_t::write_fix_try() to
try to set a fake "write fix" lock-free. If the page is currently
write-fixed between buf_page_t::flush() and
buf_page_t::write_complete(), acquire and release a page U-latch to
wait for the conflicting write to complete.

InnoDB_backup::backup_batch_start(),
InnoDB_backup::backup_batch_stop(): Adjust fil_space_t::backup_end and
fake "write fix" of dirty pages to protect the copying of a range of
pages from the underlying file.

InnoDB_backup::commit(): Enqueue the remaining log to be copied.

InnoDB_backup::checkpoint_complete(): If backup is running and
commit() has not been called, add each completed innodb_archive_log=ON
file to the queue. Else, skip or delete, as appropriate.

InnoDB_backup::archive_create(), innodb_backup_archive_create():
Hook for log_t::archive_create().

log_t::backup_start(): If we were running with innodb_log_archive=ON,
ensure that the latest file is a valid recovery starting point.
That is, wait for the latest log checkpoint to be within the file.

buf_flush_list_space(): Check for concurrent backup before writing each
page. This is inefficient, but this function may be invoked from multiple
threads concurrently, and it cannot be changed easily, especially for
fil_crypt_thread().

fil_ibd_create(): Set fil_space_t::create_lsn after the file has been
created.

dict_load_tablespaces(): Determine the size of each file if
upgrade==true. Backup depends on that.

buf_dblwr_t::begin(), buf_dblwr_t::end(), buf_dblwr_t::size():
Accessors to allow BACKUP SERVER to skip the contents of the
doublewrite buffer in the system tablespace. It is only useful for
crash recovery in case a data page had been incompletely written by
the time the server was killed. If the server is killed during a
backup, the backup will be incomplete and unusable anyway.
Furthermore, the page range locking makes page writes and backup
mutually exclusive.
Oleg Smirnov
MDEV-24684 Quadratic time for MIN/MAX/STD/VARIANCE as window functions

Rename variables and add comments for better readability
bsrikanth-mariadb
MDEV-41293: FederatedX: connection state after a net_read_timeout

Problem:
When reading the reply of the remote server times out, the client
library compiled into the server returns without closing the connection
and without setting a client error. FederatedX took the raw
ER_NET_READ_INTERRUPTED for an error of the remote server and went on
using a connection that still had the reply of the failed statement to
arrive. As a result:
* the next statement on that connection failed in various ways, either
  with ER_QUERY_ON_FOREIGN_DATA_SOURCE ("Server has gone away") or with
  an error packet that mysqltest took for a malformed packet;
* inside a transaction, the following statements continued on a new
  remote session in autocommit mode, so they were committed on the
  remote server one by one even though the local transaction was later
  rolled back. The savepoints of the lost session were also still
  remembered by FederatedX.
The same happened when the connection was lost while reading the reply.

Fix:
* After a timeout FederatedX closes the connection, so that the next
  statement opens a new one. The client still gets the error of the
  timeout, ER_NET_READ_INTERRUPTED.
* Whenever the connection is gone after a failed statement, timeout or
  not, the state of the lost session (autocommit mode, savepoints) is
  forgotten and the local transaction is marked to be rolled back, so a
  new connection starts the transaction again. The closed connection is
  also freed, which was leaked before.
* Errors of the client library are reported as
  ER_QUERY_ON_FOREIGN_DATA_SOURCE by ha_federatedx::info() as well, the
  same way as by the pushed down multi-table UPDATE/DELETE.
* The error state of ha_federatedx, read by info(), is initialized.

Test: federatedx_pushdown_upd_del covers the timeout of a pushed down
multi-table UPDATE and DELETE and of reading a result, the statements
after it, the same inside a transaction, a connection killed in the
middle of a statement, client library errors in info(), and that an
error of the remote server which merely has the code of
ER_NET_READ_INTERRUPTED is not taken for a timeout.
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
Rucha Deodhar
MDEV-23500: Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())'
failed in Diagnostics_area::set_ok_status upon multi-table update

Analysis:
When NULL field from internal temporary table is copied to
NOT-NULL so there is error about truncation  but this error is not
reported so we get the failure.

Fix:
Return the error state.
Sergei Golubchik
MDEV-41822 mariadb-binlog ASAN crash on corrupted binlog

1. verify that the null bitmap length doesn't overshoot row event end
2. pass the buffer length to calc_field_size(), so that it'd never read
  beyond the end
Lawrin Novitsky
Fix in the cppmini submodule
Kristian Nielsen
MDEV-41433: Infinite IO error on a binlog-in-engine master

When the master uses binlog-in-engine, the slave is required to connect with
GTID enabled, and an error is thrown in the dump thread if not.

However, the error thrown was a custom error code, this is not handled
correctly by the slave and resulted in the IO thread looping infinitely,
reconnecting and immediately getting error about requiring GTID mode.

Signed-off-by: Kristian Nielsen <[email protected]>
nada
MDEV-37214 CREATE OR REPLACE USER must not drop the existing account on failure

CREATE OR REPLACE USER used to DROP the existing account before validating the new definition, so a failure after the DROP (e.g. an unknown auth plugin) permanently deleted the account without writing anything to the binlog, diverging master and replicas.

Validate and prepare the new account first; only wipe the account's privileges from the non-user grant tables once all checks pass, immediately before updating mysql.user/mysql.global_priv in place. A failure now leaves the existing account untouched.

  - CREATE OR REPLACE USER/ROLE now builds the replacement from a default row (as for a new account) instead of updating the old row field by field, so password, resource limits, SSL options and lock status do not survive the replace.
  - Orphan privileges (grant-table rows with no mysql.user row) are also removed.
  - Rebuild the role/user cross-reference arrays after a successful replace; without this, SHOW GRANTS could crash on an account that had been granted a role.
Oleksandr Byelkin
Fix use-after-poison on BINLOG with a Query event in EXECUTE IMMEDIATE

Query_log_event::do_apply_event() freed thd->mem_root, which inside a
BINLOG statement also freed the statement's own memory, e.g. Items of
EXECUTE IMMEDIATE freed later in THD::cleanup_after_query().

Free thd->mem_root only in replication/wsrep appliers, as
Rows_log_event::do_apply_event() does.

Reviewed by [email protected]
Oleksandr Byelkin
MDEV-39306 fix race in versioning.rpl_row

The slave created table t before the master's previous DROP TABLE t
was replicated. Sync the slave after the drops.

Reviewed by [email protected]
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]>
Raghunandan Bhat
MDEV-40836: Window function in ORDER BY split twice by split_sum_func()

Problem:
  A window function inside an ORDER BY expression was split twice by
  `split_sum_func()` first in `setup_order()`, then again in
  `JOIN::prepare()`. Each split adds the item to `ref_pointer_array`,
  which resulted in overflow.

  The split in `setup_order()` was added by MDEV-28094 (8c34eab) to fix
  a crash in -
    SELECT EXISTS (SELECT 1 ORDER BY 1+sum(2) OVER ());

  `check_and_do_in_subquery_rewrites()` dropped the ORDER BY of that
  subquery, so `JOIN::prepare()` never split it. But its window function
  was still registered with the select and processed, causing the crash.

Fix:
  - When check_and_do_in_subquery_rewrites() drops the ORDER BY, also
    remove its window functions from `SELECT_LEX::window_funcs`.
  - Remove the window function split from `setup_order()`, so it is
    done only once, in `JOIN::prepare()`.
Rucha Deodhar
MDEV-23500: Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())'
failed in Diagnostics_area::set_ok_status upon multi-table update

Analysis:
When NULL field from internal temporary table is copied to
NOT-NULL so there is error about truncation  but this error is not
reported so we get the failure.

Fix:
Return the error state.
Rucha Deodhar
MDEV-22675: Assertion `offset < table->s->reclength' failed in dump_leaf_key

Analysis:
The reclength depends on the size of each field of the temporary table plus
the null_bytes. Since null_bytes is 0 (because we’re in non-strict mode and
the source table fields can never be null), there is no need to keep track
of null values. Hence the total record length is just the sum of the sizes
of both fields. The second field will always have size 0 because its value
will always be an empty string. Hence it starts exactly where the first
field ends which equal to reclength. Hence the assertion failure.

Fix:
If pack_length() is 0 (which means the size of field is 0) so assigning the
result as empty string directly, the assertion is not valid in that case.
Rucha Deodhar
MDEV-22675: Assertion `offset < table->s->reclength' failed in dump_leaf_key

Analysis:
The reclength depends on the size of each field of the temporary table plus
the null_bytes. Since null_bytes is 0 (because we’re in non-strict mode and
the source table fields can never be null), there is no need to keep track
of null values. Hence the total record length is just the sum of the sizes
of both fields. The second field will always have size 0 because its value
will always be an empty string. Hence it starts exactly where the first
field ends which equal to reclength. Hence the assertion failure.

Fix:
If pack_length() is 0 (which means the size of field is 0) so assigning the
result as empty string directly, the assertion is not valid in that case.
Rucha Deodhar
MDEV-36653: main.mysql_upgrade-28915 test case timeout

Analysis:
Concurrent execution of mysql_upgrade and the event scheduler causes a
metadata locking (MDL) deadlock between ALTER TABLE on system tables and
the initial loading/caching of the event table.

Fix:
Disable the event scheduler via 'SET GLOBAL event_scheduler=OFF' prior to
running the upgrade in the test case. This prevents concurrent conflicts
and allows the test to run reliably.
Aleksey Midenkov
MDEV-40821 Wrong result after DELETE HISTORY or PORTION OF (10.11)

The parser assigned versioning conditions of DELETE HISTORY ... BEFORE
SYSTEM_TIME and period conditions of DELETE ... FOR PORTION OF to the
table pointed by last_table(). When the BEFORE SYSTEM_TIME or FOR
PORTION OF expression references another table (e.g. via a subquery or
a sequence function), last_table() is already switched to that table,
and the DELETE target gets no conditions.

DELETE HISTORY then deletes current rows permanently instead of
history, keeps the history it had to purge, and is checked for DELETE
privilege instead of DELETE HISTORY. DELETE HISTORY from a
non-versioned table is not rejected with ER_VERS_NOT_VERSIONED.
DELETE ... FOR PORTION OF deletes all rows of the table, ignoring the
period.

The fix assigns the conditions to the TABLE_LIST returned by
delete_single_table, i.e. the DELETE target itself, regardless of
tables added later in the statement.

DBUG_ASSERT in TABLE::vers_switch_partition() is removed. It checked
delete_history on last_table() and assumed no other table is opened
for write by DELETE HISTORY, which is false for the underlying table
of a view or a table locked by SELECT ... FOR UPDATE in the history
point. The DELETE HISTORY target is already skipped there by its own
delete_history check.
Rucha Deodhar
MDEV-41761: SIGSEGV in sp_head::bind_input_param when trigger passes
NEW/OLD row as OUT parameter to CALL

Analysis:
When passing Item_trigger_row trigger (NEW) to an OUT parameter,
bind_input_param called get_item_splocal(). Because it returned a valid
pointer, the engine attempted to access rcontext_handler(), which is null
for trigger rows, causing a segmentation fault.

Fix:
Overriding get_item_splocal() in Item_trigger_row to return nullptr ensures
the engine safely skips the invalid context handler lookup, preventing
the crash.
Sergei Golubchik
update C/C
Rucha Deodhar
MDEV-41760: SIGSEGV in Field_iterator_table::set_table on re-prepare of
trigger SET NEW = (subquery) after DDL on referenced table

Analysis
Item_trigger_row items were not having proper setup and list tracking, so
they were not getting saved or restored during expression re-parsing.
So when table alteration happened the row items lost their correct table
resulting in assertion failure.

Fix
Added setup function and tracking lists for row items to properly handle
and re-bind items.