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
Vladislav Vaintroub
MDEV-40287 AES_ENCRYPT() and KDF() return NULL with OpenSSL 4.0

MyCTX used an EVP_CIPHER_CTX in a stack buffer instead of allocating it
with EVP_CIPHER_CTX_new(). OpenSSL 4.0 rejects a context that was not
created that way for ciphers that use an IV: EVP_CipherInit_ex() fails
with "invalid iv length", so AES_ENCRYPT() and KDF() in CBC/CTR/GCM
modes return NULL. ECB has no IV and still works, which is why only the
non-ECB modes broke.

Allocate the context with EVP_CIPHER_CTX_new()/EVP_CIPHER_CTX_free(), and
on an init error free and null it, so a later update()/finish() from a
caller that ignored the error is a safe no-op, not a double free. Remove
check_openssl_compatibility() and the EVP_CIPHER_CTX_SIZE and
EVP_CIPHER_CTX_init macros.

my_md5() used the same stack-buffer-sized-by-EVP_MD_CTX_SIZE hack, whose
only guard was check_openssl_compatibility(). MD5_CTX is a concrete struct
in both OpenSSL and WolfSSL, so use it directly with MD5_Init/Update/Final
on a caller-owned context, like my_sha.inl does for SHA*_CTX; this removes
the EVP_MD_CTX hack and EVP_MD_CTX_SIZE. The exception is OpenSSL 1.0.x,
which aborts on the low-level MD5 API in FIPS mode (MDEV-7788): there, and
only there, keep the EVP path with the non-FIPS flag. 1.1.0 removed the
FIPS Object Module and 3.0+ low-level MD5 bypasses the provider, so the
concrete MD5_CTX is correct on every other version. SHA is unaffected, it
already used concrete SHA*_CTX structs.

Verified against OpenSSL 4.0.1: the mysys aes-t test fails on the
CBC/CTR/GCM cases with the stack buffer and passes with
EVP_CIPHER_CTX_new(). The 1.0.x MD5 path verified against a FIPS build of
OpenSSL 1.0.2u: the EVP path computes MD5, the low-level path aborts.

No visible performance degradation: the extra allocation costs
~12 ns/call (WolfSSL) and ~30 ns (OpenSSL) on Windows at a 30-byte
payload, nothing at 16 KB, and nothing on Linux/glibc; sysbench OLTP
over encrypted tables and redo log is unchanged.

Tests main.tlsv13 and main.ssl_crl: OpenSSL 4.0.3 reports TLS alerts as
"tls alert ..." (was "ssl/tls alert ..."), accept both.

Assisted-by: Claude:claude-opus-4-8
Marko Mäkelä
Merge 10.11 into 11.4
Oleksandr Byelkin
MDEV-41405 ASAN stack-buffer-overflow TDBXML::Initialize/TDBXML::OpenDB after insert into CONNECT table

XmlDB was copied with strcpy/strcat into a 64-byte stack buffer to
build the XPath. Tabname used the same buffer with snprintf, silently
truncating the XPath.

Build the XPath in a buffer allocated by its real length.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Oleksandr Byelkin
Fix sporadic failure of main.charset_client_win_utf8mb4

The test set the password via "chcp 850 && echo ...", but the console
codepage is shared by all parallel mtr workers, so another process could
switch it to UTF8 and the password got stored as UTF8.

Write the cp850 password byte to a file and feed it to the client instead.
Daniel Black
MDEV-40386 enable duckdb tests for MSAN
Oleksandr Byelkin
New HeidiSQL v12.21
Alessandro Vetere
MDEV-41557 Test encryption.innochecksum is flaky

The test checks that sys.innodb_buffer_stats_by_table reports old
pages (pages_old) after a server restart. InnoDB creates the old
sublist of the buffer pool LRU list only when the list holds at least
BUF_LRU_OLD_MIN_LEN (512) pages. After the restart, most of the pages
in the list come from the buffer pool load at startup. This load runs
asynchronously, and the server accepts connections before it
completes. If the test runs the check first, the list can be shorter
than 512 pages, no page is old, and the result shows 0 instead of 1.

The option --innodb-buffer-pool-load-at-startup=0 disables the load.
This is the extreme case of the race: the check always runs before
any page of the dump is loaded. With this option, the test fails every
time with innodb_page_size=4k and 16k.

Wait for the buffer pool load to complete before the check, as other
tests do.
Aleksey Midenkov
MDEV-40380 vcol.races sporadic timeout

After MDEV-39261 purge opens TABLE via open_purge_table() for any
undo record of a table with indexed virtual columns, including the
insert undo record. If purge does that after FLUSH TABLES, the TABLE
is put back into the table cache. Then DELETE from con1 reuses the
cached TABLE, skips open_table_from_share() and never hits the
TABLE_after_field_clone sync point. DELETE completes immediately,
wait_condition times out and SELECT returns an empty set.

The fix waits for purge to complete before FLUSH TABLES.
Aleksey Midenkov
MDEV-41583 Tests fail on platform-dependent max TIMESTAMP of current row

versioning.partition (MDEV-41543) and main.grant2 (MDEV-41099) print
row_end of the current row. Since MDEV-32188 in 11.5 the max TIMESTAMP
is 2106-02-07 06:28:15.999999 on 64-bit and 2038-01-19 03:14:07.999999
on 32-bit, so the results recorded on 64-bit fail on 32-bit.

The fix prints CURRENT instead of row_end of the current row in
versioning.partition (using current_row_ts() from common.inc) and
replaces row_end with # in main.grant2, where only the privilege to
read it is tested.

Affected since 11.8. The fix is committed to the originating 10.11 to
minimize conflicts.
Aleksey Midenkov
MDEV-17613 Test cleanup: sorted result for versioning.partition

Avoid result fluctuations with different storage engines.
Aleksey Midenkov
MDEV-25529 Auto-create: Pre-existing historical data is not partitioned as specified by ALTER

Adds logic into prep_alter_part_table() for INTERVAL ... AUTO to read the
history range (vers_get_history_range()) and size the new layout from it.
STARTS is aligned to the oldest history row_end (vers_set_starts()) if it
was not specified by the user, or if the user specified it later than
that; in the latter case WARN_VERS_WRONG_STARTS is printed. The history
partitions cover both the newest history row_end and the query time, so
DML after the ALTER does not need to create partitions. A PARTITIONS N
clause is kept if it gives more partitions. An explicit subpartition list
is replaced by as many default subpartitions. If the layout needs more
than MAX_PARTITIONS partitions (counting subpartitions), or the INTERVAL
is longer than the date range, the ALTER fails with
ER_VERS_HIST_PART_FAILED. Month and year intervals are stepped in UTC; a
boundary past the maximum TIMESTAMP ends a partial last history
partition.

In case of fast ALTER TABLE, f.ex. when partitioning already exists, the
above logic is ignored unless FORCE clause is specified. When user
specifies partition list explicitly the above logic is ignored even with
FORCE clause. With FORCE on a table already partitioned by SYSTEM_TIME
the work is done on a clone of the partitioning info. The parsed settings
are copied into the clone's vers_info with
Vers_part_info::copy_settings(), which keeps the clone's now_part and
hist_part (the parsed ones are NULL).

Before reading the range, the metadata lock is upgraded to
MDL_SHARED_NO_WRITE, and then the copy does not run online, so DML
cannot add history that would not fit the computed layout until the
ALTER ends (Alter_info::vers_history_read). LOCK=NONE and
ALGORITHM=INPLACE/NOCOPY/INSTANT are rejected for such ALTER before the
upgrade, so they do not wait for concurrent DML; the ALGORITHM error is
reported by the new Alter_info::report_algorithm_unsupported(), which
mysql_alter_table() uses as well. The range is read under a table lock
taken with mysql_lock_tables(), as some engines (Aria) set up their
transaction in THR_LOCK callbacks. The scan can be killed.

WARN_VERS_STARTS_BEYOND_INTERVAL for ALTER .. AUTO is checked after the
alignment, so it is not printed when STARTS was re-aligned to the history.

vers_get_history_range() detects if an index can be used for row_end
min/max stats and if so it gets it with ha_index_first() and
HA_READ_BEFORE_KEY (as it must ignore current data). Otherwise it does a
table scan to read the stats. Current rows with the pre-11.5 row_end
marker are not taken for history either. In the index they sort below
history after 2038, so the minimum is read after them. There is
test_mdev-25529 debug keyword to check the both and compare results.
WARN_VERS_SLOW_ROW_END is printed if the scan read any row and there is no
usable index (a disabled one does not count as missing).

Static key_cmp was renamed to key_eq to resolve compilation after key.h
was included as key_cmp was already declared there.
Aleksey Midenkov
MDEV-17613 Read sole now-partition for non-historical versioned query

When a versioned table stores its history in partitions, an implicit
query (no FOR SYSTEM_TIME) needs only current rows, which all live in
the current partition. vers_setup_conds() no longer adds a row_end
condition for such a table, and prune_partitions() restricts
read_partitions to the current partition instead.

read_partitions is reset to all partitions every statement in
open_table(), so the restriction must be applied on each execution.
prune_partitions() runs on each execution, also for merged derived
tables and views, where vers_setup_conds() is not called again. Both
functions guard with !vers_conditions.was_set(). In prune_partitions()
!is_set() would not do: set_all() sets type (flips is_set()) but not
orig_type (was_set()), so is_set() would be true on prepared-statement /
stored-procedure re-executions and skip the restriction, leaving history
partitions readable - rows matched then grow on each execute/call.

A query whose time comes from @@system_versioning_asof must still read
history, so the restriction is also skipped when from_sysvar is set.
init_from_sysvar() sets this new flag rather than orig_type, so
was_set(), print() and the write lock check still see only an explicit
FOR SYSTEM_TIME. Like orig_type, the flag persists to prepared-statement
re-execution.

EXPLAIN no longer shows "Using where" for such a query: correctness now
comes from partition selection rather than a row_end filter.

With sql_safe_updates, DELETE without WHERE on such a table is now
rejected even with LIMIT, as for a non-versioned table. With an index
on row_end, UPDATE or DELETE without WHERE (UPDATE also without LIMIT)
is now rejected too: it was accepted as a range scan on row_end. A
versioned table without SYSTEM_TIME partitions keeps the old behavior
(MDEV-41393).
Alessandro Vetere
MDEV-41398 Stale optimistic btr_pcur_t restore after buffer pool resize

Problem: btr_pcur_t::restore_position() accepts a stored position
optimistically when the block at the stored descriptor address has the
same page id and the same buf_block_t::modify_clock. When
buf_pool_t::resize() shrinks the buffer pool, the withdrawn block
descriptors are freed. When it grows the buffer pool again, the new
descriptors at the same addresses start with modify_clock=0. A cursor
that was stored before the shrink can then find a different instance of
the page with an equal modify_clock, and it restores to a record that
is no longer correct. In a release build, an UPDATE can change a row
that does not match its WHERE condition and skip the rows that match.

Fix: Add buf_pool_t::withdrawn_modify_clock. buf_pool_t::shrink() sets
it to the maximum modify_clock of the blocks that it withdraws.
buf_pool_t::resize() sets the initial modify_clock of each block that
it adds to one more than this. A relocation in shrink() increments only
the modify_clock of the destination block, so a withdrawn block can
keep the value that a cursor stored. Thus the modify_clock at a block
descriptor address never repeats an earlier value, and a stale
optimistic restore fails. The new member uses a hole before
buf_pool_t::flush_list_mutex, so the layout of the other members does
not change.

The test innodb.buf_pool_resize_pcur_restore reads a page into the
first new block after a grow, and makes a stored cursor for a read and
for an UPDATE restore its position across a page reorganization, a
shrink and a grow.
Aleksey Midenkov
MDEV-17613 Refactor prune_partitions() to build into a dedicated bitmap

prune_partitions() built the used-partition set directly in
read_partitions: it cleared it, let find_used_partitions*() fill it, and
in the index-merge case used it as scratch too - both buffer and result.

The patch adds PART_PRUNE_PARAM::parts_bitmap and builds the return
into it instead. read_partitions is produced from it only at the end:
copied when the condition was analyzed (IMPOSSIBLE included,
parts_bitmap left empty), or set to all locked partitions via
mark_all_partitions_as_used() when nothing could be pruned.

Pure refactoring: read_partitions ends up identical on every path. It
decouples the pruning scratch from read_partitions, so a later commit can
switch the final bitmap_copy() to bitmap_intersect() - letting pruning
narrow a pre-set read_partitions (e.g. a versioned table selecting only
its current partition) instead of overwriting it.
Aleksey Midenkov
MDEV-17613 bitmap_range() for iteration over partition bitmap

Returns bit range for partition element.
Vladislav Vaintroub
MDEV-41508 Off-by-One Uninitialized Stack Read in Proxy Protocol V2 Port Parsing

parse_v2_header() required only 25 (TCPv4) / 49 (TCPv6) bytes, but then
reads the source port at hdr[25] / hdr[49]. A truncated header could make
it read uninitialized stack.

Require the whole address block: 28 bytes for TCPv4 and 52 for TCPv6.

Also, the declared header length was trusted without checking how many
bytes vio_read() returned. Reject short reads. The spec requires the
sender to send the header at once, and allows the receiver to drop the
connection on a partial header, so a single vio_read() is enough.

The v1 parser had the same problem on EOF: vio_read() returning 0 was
taken for a byte read, so the uninitialized buffer was parsed. Require
exactly one byte.

Extend test_proxy_header_tcp with a header cut short before the port,
and add test_proxy_header_short for a header shorter than it declares.

Light refactoring, to avoid repetition: added connect_tcp() and
init_v2_header(), which are now shared by several proxy header tests.

Assisted-by: Claude:claude-sonnet-5-5
Sergei Golubchik
MDEV-34817 perfschema.lowercase_fs_off fails on buildbot

initialize counters when constructing a new PFS_program object

The test fails because a newly created routine can get a performance
schema slot freed by a routine dropped in an earlier test. The counters
of a reused slot are not reset, so the new routine shows the old
routine's statistics.
forkfun
MDEV-39146 Fix stack-use-after-return in PROCESSLIST for event threads

Event_job_data::execute() pointed thd->security_ctx at a local
Security_context. A concurrent PROCESSLIST scan captures that pointer
without a lock and can read it after execute() returns.

Make the Security_context a member of Event_job_data, which lives in
Event_worker_thread::run() until after thd is deleted.

Add main.events_debug test
Daniel Black
MDEV-40698 Fix ROLLUP query results with empty result set (testfix)

Like b3830bce9a7e12851feb7e6d6b4e0d33a66ba8af, this corrects the ROLLUP
result of the duckdb.duckdb_sql_syntax test to have a NULL row when
there is an empty result set.
Oleksandr Byelkin
new wolfssl v5.9.4-stable
sjaakola
MDEV-41553 galera_restart_on_unknown_option test regression after MDEV-40023

The problem with the test was that it restarted node 2 by writing
"try:--galera-unknown-option" into the expect file. However, MariaDB mtr has
never supported a "try" command. Instead mtr skipped any expect file line not
starting with "restart", and node 2 was not started with the unknown option
(which was the idea in the test logic). The test only slept and then restarted
node 2 normally.
MDEV-40023 made mtr report unknown expect file commands as errors,
so the test now fails in 13.1 and later.

The fix is to start node 2 with the unknown option directly with --exec.
In cluster, the unknown option is found only after the state transfer has started.
The server should interrupt the state transfer and abort.

Galera version 26.4.25 or later is needed for graceful shutdown, and this is now
required by the test.
Oleksandr Byelkin
new PCRE2 10.49
Daniel Black
MDEV-40386: DuckDB - pass through compiler and linker flags

Without passing through the compile and linker flags, options
like -stdlib=libc++ can create ABI differences between ducksdb
extensions and what the server links too.

The jemalloc has C files so CMAKE_C_FLAGS is passed through too.
Aleksey Midenkov
MDEV-17613 Refactor prune_partitions() to narrow read_partitions instead of full rewrite

read_partitions is reset to all partitions (or the PARTITION() set) once
per statement in open_table() (set_partition_bitmaps()), and
prune_partitions() only intersects it with lock_partitions and the pruned
set instead of rebuilding it.
mark_all_partitions_as_used() is dropped.

Pure refactoring, results unchanged. It lets a restriction set on
read_partitions before pruning survive it - needed when read_partitions
is pre-restricted, e.g. a versioned table whose history is partitioned
reads only the current partition.
Daniel Black
MDEV-40845: DuckDB: reject SELECT ... FOR UPDATE / LOCK IN SHARE MODE (msan)

Works under MSAN just fine.
Oleksandr Byelkin
MDEV-22374 VIEW with security definer require FILE privilege from definer not invoker in case of INTO OUTFILE

Already fixed by MDEV-39493; add a test for the view case.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Oleksandr Byelkin
New 3.3 CC
Aleksey Midenkov
innodb.innodb_buffer_pool_resize_temporary fails with (0/506)

The test reads innodb_buffer_pool_resize_status while the
SET GLOBAL innodb_buffer_pool_size thread is blocked at
buf_pool_shrink_before_wakeup and expects nothing withdrawn yet:

  Withdrawing blocks. (505/505).

But buf_pool_t::resize() sets n_blocks_to_withdraw and
first_to_withdraw and releases buf_pool.mutex before that sync
point. From then on other threads withdraw blocks: allocate() from
any page allocation, buf_LRU_block_free_non_file_page() on eviction,
and the page cleaner LRU batch which evicts pages from the withdrawn
area while to_withdraw is nonzero. So the first counter can be
anything down to 0:

  Withdrawing blocks. (0/506).

The fix masks the first counter in replace_regex, so the result
does not depend on how many blocks were already withdrawn.

This does not weaken the test: it still checks that the shrink is
reported while in progress. How many blocks are already withdrawn at
that moment depends only on timing.
Marko Mäkelä
Merge 11.4 into 11.8
iff-sal
MDEV-40297: SET changes @@default_master_connection's system variable if the explicit connection name is blank

When updating replicate_do_db and slave_parallel_mode, the handlers
checked !base_name->length instead of !base_name->str to determine
whether to fall back to @@SESSION.default_master_connection.

Because an explicit blank qualifier (``) has length 0 with a non-NULL
pointer, SET statements using empty backticks mistakenly updated
default_master_connection rather than the unnamed connection.

Fixed by checking !base_name->str instead of !base_name->length.

Also fixed SELECT @@GLOBAL.slave_parallel_mode, which had the same
issue when reading the variable.

Renamed the regression test to sys_vars_default_master to reflect
the broader coverage and merged the test cases of
MDEV-40296 and MDEV-40297.

Reviewed-by: ParadoxV5 <[email protected]>
Alessandro Vetere
MDEV-40123 Assertion failure after lock wait is unblocked in SKIP LOCKED

A locking read with SKIP LOCKED through a secondary index calls
row_sel_get_clust_rec_for_mysql() to lock the clustered index record.
On a lock conflict, that function returned DB_LOCK_WAIT without
setting the output record, and row_search_mvcc() then called
lock_trx_handle_wait() to cancel the wait. If the conflicting
transaction had committed in the meantime, the waiting lock was
already granted and lock_trx_handle_wait() returned DB_SUCCESS.
row_search_mvcc() then found clust_rec == NULL for a locking read:
debug builds failed an assertion, and release builds skipped a row
whose lock the transaction now held.

Row_sel_get_clust_rec_for_mysql::operator()(): Call
lock_trx_handle_wait() here instead of in row_search_mvcc(). When
the lock was granted meanwhile, return the clustered index record
and store the cursor position as for any granted lock, like
row_search_mvcc() does with "goto locks_ok" for the record that it
is positioned on.
ParadoxV5
MDEV-32947 Async conflicts with semi-sync in multi-source

`@@rpl_semi_sync_slave_enabled` can be changed without stopping
replication, because it takes effect when a connection is established.
But when it takes effect, it applies to *all* replication connections.
This means that starting an async connection will switch any ongoing
semi-sync connections to async as well, and vice versa, which will
cause those connections to fail to replicate in the wrong mode.

This fix resolves this oversight by changing the value application
to be specific to only the establishing connection (technically,
moving the singleton’s field `Repl_semi_sync_slave::m_slave_enabled`
to the instance variable `Master_info::semi_sync_enabled`).
This design builds toward MDEV-40941, which proposes migrating
`@@rpl_semi_sync_slave_enabled` to a proper per-connection config.
Note, `Master_info::semi_sync_reply_enabled` must remain separate,
because it only disables ACK replying in async slave fallback,
whereas the semi-sync slave setting also controls whether the IO
thread should expect additional semi-sync flags in event packets.

To maintain backward compatibility until MDEV-40941,
the status variable `Rpl_semi_sync_slave_status` is kept showing
the applied `@@rpl_semi_sync_slave_enabled` for the most recent
START SLAVE in any connection; that is, not yet made per-connection.

Reviewed-by: Brandon Nesterenko <[email protected]>
Georg Richter
Add placeholder in emum_stmt_attr_type

Since value 207 (STMT_ATTR_SQL_STATEMENT) is already used in 3.4
we have to add a placeholder (STMT_ATTR_UNUSED).
Dave Gosselin
MDEV-41146:  Merge pseudo_bits_cond into outer_ref_cond

A join of only const tables stored the WHERE conjuncts that refer to a
column of an outer query or call rand() in pseudo_bits_cond.  The
executor read pseudo_bits_cond only when the query needed no temporary
table, and read outer_ref_cond otherwise.  A window function or
DISTINCT with ROLLUP needs a temporary table, so those conjuncts were
never checked, and the query returned rows that the WHERE clause
rejects.

pseudo_bits_cond came from the fix for LP bug 908269 in 2012.  For a
join of only const tables, that fix also collected conjuncts that call
rand(), and it stored them in a new field without stating a reason.
The code that filled the two fields and the code that read them chose
between them by the same test.  The tests have differed since
MDEV-8646 in 2016, which added the temporary table condition to the
executor's test.  Later changes only display the field, in EXPLAIN
FORMAT=JSON (MDEV-19714) and in the optimizer trace (MDEV-21095).  In
MDEV-19714, its author wrote that it was not clear why pseudo_bits_cond
was needed in addition to outer_ref_cond.

pseudo_bits_cond is removed, and outer_ref_cond holds these conjuncts
for every join.  The executor checks it on both paths, so where the
conjuncts are stored no longer depends on the executor's test.
Conjuncts that call rand() are still collected only for a join of only
const tables.  EXPLAIN FORMAT=JSON shows these conjuncts as
outer_ref_condition instead of pseudo_bits_condition.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Oleksandr Byelkin
Fix MSAN failure in mysqltest with --cursor-protocol after CC update

CONC-821 in Connector/C 3.3.21 no longer resets *length for string
binds, so for NULL values the length array in append_stmt_result()
stayed uninitialized. Zero-fill it on allocation.
Aleksey Midenkov
MDEV-40854 Use of uninitialized table_will_be_deleted in federated engine

MemorySanitizer report:

==851408==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 ha_federated::end_bulk_insert() storage/federated/ha_federated.cc:2035:30
    #1 mysql_insert(THD*, ...) sql/sql_insert.cc:1258:11
    ...
  Memory was marked as uninitialized
    #0 __msan_allocated_memory
    #1 my_malloc mysys/my_malloc.c:116:7
SUMMARY: MemorySanitizer: use-of-uninitialized-value ... end_bulk_insert()

table_will_be_deleted is a handler member with no in-class
initializer, and the handler object itself is heap-allocated via
my_malloc(), so it starts out as garbage. It was only ever set in
extra(HA_EXTRA_PREPARE_FOR_DROP) and in external_lock(). For a
TEMPORARY table, statement execution can reach end_bulk_insert(),
which reads the flag, without external_lock() having run first, so the
read sees uninitialized memory.

The fix initializes table_will_be_deleted in reset(). Both
ha_federated::open() and ha_federatedx::open() call reset(), so the
flag is initialized on first open and cleared after every statement.
That also covers the first statement after open (e.g. CREATE TEMPORARY
TABLE ... ENGINE=FEDERATED ... SELECT, where external_lock() is not
called).
Val Doroshchuk
MDEV-40845: DuckDB: reject SELECT ... FOR UPDATE / LOCK IN SHARE MODE

DuckDB has no row locks and its parser rejects locking clauses, so
SELECT ... FOR UPDATE on a DuckDB table failed with ER_GET_ERRMSG
("Parser Error: SELECT locking clause is not supported!") coming from
the embedded DuckDB.

Check for locking reads in ha_duckdb::external_lock() and raise
ER_NOT_SUPPORTED_YET from the storage engine instead. The check only
applies to SQLCOM_SELECT, so INSERT ... SELECT, UPDATE and DELETE are
not affected.
Dave Gosselin
MDEV-41146:  Check rand() in WHERE when top level base tables are const

A WHERE conjunct that calls rand() but doesn't refer to a column, such
as rand() < 0, is checked on the last non-const top level base table
in the join order.  A join of only const tables has no such table and
returns at most one row, so the conjunct is checked once before the
join starts, together with the conditions on columns of an outer
query.

When every top level base table is const and materialized semi-joins
follow them, the join order also has no non-const top level base
table, but only_const_tables() is false.  The conjunct was never
checked, and such a query gave wrong results.

The check before the join now applies whenever the join order has no
non-const top level base table, which is the same condition under
which no table in the join order receives the conjunct.  Such a join
also returns at most one row.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Aleksey Midenkov
MDEV-40854 Use of uninitialized table_will_be_deleted in federated engine

MemorySanitizer report:

==851408==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 ha_federated::end_bulk_insert() storage/federated/ha_federated.cc:2035:30
    #1 mysql_insert(THD*, ...) sql/sql_insert.cc:1258:11
    ...
  Memory was marked as uninitialized
    #0 __msan_allocated_memory
    #1 my_malloc mysys/my_malloc.c:116:7
SUMMARY: MemorySanitizer: use-of-uninitialized-value ... end_bulk_insert()

table_will_be_deleted is a handler member with no in-class
initializer, and the handler object itself is heap-allocated via
my_malloc(), so it starts out as garbage. It was only ever set in
extra(HA_EXTRA_PREPARE_FOR_DROP) and in external_lock().  For a
TEMPORARY table, statement execution can reach
end_bulk_insert()/write_row(), which reads the flag, without
external_lock() having run first, so the read sees uninitialized
memory.

The fix initializes table_will_be_deleted in reset(), which runs
after each statement, so the flag is cleared before the next
statement reaches end_bulk_insert() regardless of locking path.