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
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]>
Daniel Black
MDEV-40386 enable duckdb tests for MSAN
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.
DerZc
MDEV-39969: Incorrect result of JSON_TABLE with BIT

Problem: JSON_TABLE maps JSON numbers [0,1] to BIT(1) values [1,1].
The scalar helper passes decimal text to BIT's binary-string store,
so the byte for '0' is 48 and is clipped to 1.

Fix: Add Field::store_numeric() for number literals serialized as text,
including fractions and exponents, and use it for JSON_TABLE numbers.
BIT parses these literals as rounded unsigned integers and applies its
existing range checks. Other fields retain their existing conversion;
JSON strings and booleans retain their existing storage paths.
Preserve the existing distinction between conversion warnings and JSON
structural errors, so numeric overflow does not invoke ON ERROR.
Extend json.json_table to cover BIT widths, unsigned boundaries,
fractions, exponents, boolean/string/null inputs, other field types,
conversion warnings and ON ERROR responses.

Assisted-by: OpenAI Codex:gpt-6
Andrei Elkin
MDEV-41214 PURGE BINARY LOGS does not delete non-active binlog files

PURGE BINARY LOGS could end with a warning instead of deleting files, as
the test below shows when run on the base of this commit. The warning
names a wrong reason. It follows an automatic purge that was refused by
the slave guard, slave_connections_needed_for_purge: the automatic purge
does not delete a binlog while it might still be needed by a slave, not
necessarily a connected one, that is while fewer than the variable's
number of slaves are connected.
Since MDEV-34504 the manual PURGE is meant to ignore the guard.
Yet it still protects a binlog that a slave is reading.

Technically this was possible because the automatic and the manual purge
share a code path, can_purge_log(), which cached the refusal and replayed
it, under the reason of the first arm below, to any later purge:

  if (is_active(name) ||
      (!is_relay_log && waiting_for_slave_to_change_binlog &&
      purge_sending_new_binlog_file == sending_new_binlog_file &&
      !strcmp(name, purge_binlog_name)))
    reason= "it is the current active binlog";

So "active" had to be read as "active or busy". The fix removes this
duality too: the two arms are now separate and have their own reasons.

The main issue is fixed by narrowing the busy arm with an additional
`!interactive &&` conjunct, so that a manual PURGE never consults the
cached refusal.

Running the test below on an unfixed 11.4 server (source tree at commit
42038e1145d) fails with "Result length mismatch" and, in part 2, this
diff against the recorded result:

  PURGE BINARY LOGS TO 'master-bin.000006';
  +Warnings:
  +Note 1375 Binary log 'master-bin.000003' is not purged because it is the current active binlog
  SHOW WARNINGS;
  Level Code Message
  +Note 1375 Binary log 'master-bin.000003' is not purged because it is the current active binlog
  show binary logs;
  Log_name File_size
  +master-bin.000003 #
  +master-bin.000004 #
  +master-bin.000005 #
  master-bin.000006 #
  master-bin.000007 #
  master-bin.000008 #

Test binlog.binlog_purge_stale_refusal_cache: the test sets
slave_connections_needed_for_purge=1, binlog_expire_logs_seconds=0 and
max_binlog_total_size=0 first and restores them at the end. It starts
with RESET MASTER so that the binlog names, 000003 and so on, do not depend
on the tests run before it in the same mtr environment. Part 1 is a control with
nothing cached; part 2 makes an automatic purge refuse 000003 (the files
must be older than binlog_expire_logs_seconds, hence --real_sleep 2 before
the rotation) and then runs PURGE BINARY LOGS TO 'master-bin.000006',
which must remove 000003..000005.

As a workaround, a PURGE could work if the following settings are made
before it, in this order:

  SET GLOBAL binlog_expire_logs_seconds=0, slave_connections_needed_for_purge=0;

The second setting invalidates the cached refusal. The first one keeps
the purge that this setting triggers from refusing and caching again.
Note that both settings change the server's policy, not only this one
PURGE: the time-based expiry and the slave guard are off until they are
restored.
Aleksey Midenkov
MDEV-17613 Test cleanup: sorted result for versioning.partition

Avoid result fluctuations with different storage engines.
Aleksey Midenkov
MDEV-41545 Unchecked get_clone() in ALTER of partitioned table crashes on out-of-memory

get_clone() returns NULL on out-of-memory, but two of its callers in
prep_alter_part_table() dereferenced the result without a check, so the
server crashed:

  changed INTERVAL of SYSTEM_TIME partitioning
  ADD PARTITION under LOCK TABLES

get_clone() itself did not check the allocation of Vers_part_info and
dereferenced it.

handle_alter_part_error() did not check the clone either. The clone only
kept the DDL log entries after the table is closed. In the branch where
DDL log recovery fails, write_log_completed() released the entries
through lpt->part_info, which the table close may have freed, and
release_log_entries() released the same entries again through the
clone. That branch is not reachable now, as ddl_log_execute_entry()
always returns false.

The fix checks the allocation of Vers_part_info in get_clone() and the
result of get_clone() in prep_alter_part_table() like the other callers
there do. handle_alter_part_error() keeps a copy of DDL_LOG_STATE
instead of the clone and passes it to write_log_completed() and
release_log_entries(), which now take DDL_LOG_STATE. The redundant
release_log_entries() after write_log_completed() is removed.
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).
Vladislav Vaintroub
MDEV-33480 Windows MSI installer, convert from WIX v3 to supported versions

WiX v3 is out of support. Support legacy WiX v3.x (default) and modern
WiX (wix.exe, newer than v3). WXS sources stay in v3 format, modern WiX
(-DWITH_WIX3=OFF) builds them after on-the-fly 'wix convert'.

Two WXS edits make the converted sources valid: ALLUSERS property is
replaced by InstallScope='perMachine', and ProgramMenuFolder is moved
from under INSTALLDIR to TARGETDIR.

WIX_ACCEPT_EULA=ON accepts the EULA of WiX 7 and later, if WiX asks for it.

A failed WiX step is reported by name.
Yuchen Pei
MDEV-40978 Restrict INTERVAL of range interval partitioning to partition-function-safe constant expressions

INTERVAL is evaluated at parse time, when placeholders and stored
procedure variables have no value yet.

We reuse the `check_partition_func_processor` to check for this. It
also bans user and system variables as well as functions lik RAND(),
but nonetheless slightly stricter than strictly needed - for example,
`CONCAT('1','.','30') HOUR_MINUTE` is no longer allowed.
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-30441 ASAN heap-use-after-free in Field_blob::pack/pack_row

When InnoDB computes an indexed virtual column (e.g. the long unique
hash), TABLE::update_virtual_field() walked its expression with
update_vcol_processor() and recomputed every vcol it referenced,
including STORED ones. innobase_allocate_row_for_vcol() saves and
restores Field_blob::value only for non-stored blob vcols, so
recomputing a STORED blob vcol in Field_blob::store_field() did
val_str(&value) and freed the buffer that record[0] still pointed to.
The row-format binlog then packed record[0] from freed memory.

The buffer is allocated only when the value is converted, so the bug
needs a character set conversion (e.g. BLOB to utf8mb3 TEXT).

The fix skips STORED vcols in update_vcol_processor(). Their values are
already in the record: InnoDB copies them as base columns of the
virtual column, and the SQL layer computes them before writing.

The test cases detect the bug only under ASAN or Valgrind.
Thirunarayanan Balathandayuthapani
MDEV-38942: Fix memory leak in dict_sys_tables_rec_read()

- Free the heap before returning READ_NOT_FOUND for a
delete-marked SYS_TABLES record.
Aleksey Midenkov
MDEV-17613 bitmap_range() for iteration over partition bitmap

Returns bit range for partition element.
Hemant Dangi
MDEV-35812: generate-ssl-certs.sh: remove bashism

Issue:
generate-ssl-certs.sh is a /bin/sh script but uses process substitution
(<(printf ...)) for -extfile, which fails with plain sh.

Solution:
Write the extensions to a file in gcadir/ and pass it to -extfile.
Vladislav Vaintroub
MDEV-39183 CONNECT JDBC: JVM is loaded from bin\client on Windows

GetJVM() only looked for %JAVA_HOME%\bin\client\jvm.dll, and for the
RuntimeLib registry value of the "Java Runtime Environment" key. Since
JDK 9 there is no "client" JVM, jvm.dll is in bin\server, and the JDK
installers write JavaHome, but not RuntimeLib, under JavaSoft\JDK.

Look for jvm.dll the way Java installations are laid out. Prefer
bin\server over bin\client, in the JDK and in its jre subdirectory.
Without connect_jvm_path (which stays exclusive, as before), try
JAVA_HOME first, then the JavaSoft\{JDK|JRE} registry keys:
CurrentVersion, then the RuntimeLib or JavaHome value of that version.

Keep the first meaningful LoadLibrary or registry error (e.g. a 32/64
bit mismatch) rather than the "not found" of the last probe, reject
over-long paths instead of truncating them, accept REG_EXPAND_SZ
values, ignore an empty JAVA_HOME, and remove a stray printf to stdout.

Tested manually with Oracle JDK 23: with JAVA_HOME unset (registry),
with JAVA_HOME set, and with an invalid JAVA_HOME falling back to the
registry.

Assisted-By: Claude:claude-5.5-sonnet
Vladislav Vaintroub
MDEV-33480 Windows MSI installer, convert from WIX v3 to supported versions

Custom actions : get rid of wcautil and dutil library dependencies
They are not an official part of WiX distribution anymore.

Replace the functionality with native MSI api, the Wix helpers
we used were thin wrappers anyway.

Also replace the VBScript FakeFailure custom action with a native
one, VBScript is deprecated in Windows and scheduled for removal.

Read MSI properties with a helper that handles any length and reports
errors. Values are no longer silently truncated to MAX_PATH, e.g a long
data directory could be cut to its parent, and then removed.

A custom action that fails to read a property or to call a Windows API
returns ERROR_INSTALL_FAILURE, it was silently ignored before.
greypilgrim-083
MDEV-40995 concurrent INSERT ... SELECT on a partitioned InnoDB table can leave the table-level AUTO_INCREMENT counter behind MAX(pk), so later inserts are handed ids that already exist and fail with ER_DUP_ENTRY on the PRIMARY KEY

For a partitioned InnoDB table with AUTO_INCREMENT as the leftmost PK
column, values are issued by the partitioning layer from the shared
counter Partition_share::next_auto_inc_val, reserved in doubling blocks
(1, 2, 4, 8 ... values per reservation).

At end-of-statement, ha_partition::release_auto_increment() returns
unused tail values to the shared counter. When a row fails mid-statement,
handler::restore_auto_increment() rolls next_insert_id back to the
boundary of an earlier block. The guard in release_auto_increment()
inspects only the last interval, so it passes even when the returned
value is already in use by concurrent sessions.

Fix: extend the guard to also verify that next_insert_id is within the
statement's own reservation interval, rejecting a lowering caused by
restore_auto_increment() rolling back across a block boundary.
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.
Jan Lindström
MDEV-39056 : sporadic test failures with galera.galera_toi_ddl_nonconflicting

The test sent

  ALTER TABLE t1 ADD COLUMN f3 INTEGER; INSERT INTO t1 VALUES (NULL, 10000, 10000);

from node_2 as a single --send. Nothing ordered that INSERT against the
CREATE UNIQUE INDEX issued from node_1, so the second DDL could reach node_2
while the INSERT was still executing there and BF-abort it. The automatic
autocommit retry then replicated with last_seen_seqno behind the seqno of the
DDL and failed certification against its exclusive key on test.t1. As
wsrep_retry_autocommit defaults to 1 there was no second retry and the client
got ER_LOCK_DEADLOCK.

Send only the ALTER TABLE and execute the INSERT after both DDL statements
have completed on both nodes.

Waiting for the second DDL by polling INFORMATION_SCHEMA.PROCESSLIST did not
prove that it had been ordered either: wsrep_TOI_begin() sets the
"Waiting to execute in isolation" stage before it replicates the writeset, so
that state can be observed before the DDL has reached total order. Wait on
node_2 for the new index to appear instead, which happens only once the DDL
has been ordered behind the parked ALTER TABLE, and record on node_1 that
neither DDL has been applied there while the first one is still parked.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Jan Lindström
MDEV-41505 : Sql_cmd_show_routine_code::execute does not call wsrep_sync_wait()

There was no wsrep_sync_wait on Sql_cmd_show_routine_code::execute.
DerZc
MDEV-41067: Fix JSON_OVERLAPS for nested arrays

Problem: JSON_OVERLAPS treats unequal nested arrays as equal when only
one parser reaches the array end. Requiring both ends also exposes a
cleanup issue: scanning ']' moves stack_p to the parent, so skipping
the current level consumes parent elements. This misses the common [2]
in [[1],[2]] and [[],[2]], and can skip unequal recursive elements.

Fix: Require both parsers to reach JST_ARRAY_END. Remember their array
levels before comparing and skip to those saved levels after completed
comparisons and mismatches, preserving parent siblings. Explain why the
saved levels are needed. Add regression coverage for both argument
orders, unequal lengths, empty arrays, recursive comparisons, type
mismatches, array order and a later common object member.
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.
Sergei Petrunia
Disable -Wredundant-move warnings in storage/rocksdb

The warnings were in RocksDB (not MyRocks) and looked like this:

rocksdb/db/db_impl/db_impl.cc: In member function ‘virtual rocksdb::Status
  rocksdb::DBImpl::FlushWAL(bool)’:
rocksdb/db/db_impl/db_impl.cc:1329:23: warning: redundant move in return
  statement [-Wredundant-move]
1329 |      return std::move(io_s);
      |              ~~~~~~~~~^~~~~~
Daniel Black
MDEV-40845: DuckDB: reject SELECT ... FOR UPDATE / LOCK IN SHARE MODE (msan)

Works under MSAN just fine.
Sergei Golubchik
Merge branch '10.11' into 11.4
DerZc
MDEV-39194: Fix DISTINCT bit and hex aggregation

Problem: SUM(DISTINCT b'1100') returns 9 instead of 12. The hybrid
hex/bit literal handler uses the default DOUBLE temporary field, so
its byte length becomes a DOUBLE(M,0) display width and clips the
numeric value.

Fix: Override numeric DISTINCT field construction for hybrid hex and
bit literals to allocate an unsigned Field_longlong directly. Preserve
argument-based field selection for other types so DISTINCT retains the
input expression's precision and scale, including decimal AVG inputs.
Extend main.sum_distinct to cover bit and hex literals, zero, byte and
unsigned 64-bit boundaries, duplicates, AVG, COUNT and decimal scale.

Recreated-by: Georgi "Joro" Kodinov <[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]>
Rex Johnston
MDEV-41179 MAX_KEY_PARTS ranges in select causing SEGV

When a select containing 32 ranges is made on a table containing a
compound key with 32 parts, the range optimizer can run off the end
of a stack variable, invalidly overwriting subsequent stack variables.

In the struct st_sel_arg_range_seq, we have an array
  RANGE_SEQ_ENTRY stack[MAX_REF_PARTS];

MAX_REF_PARTS is 32.

check_quick_select
  / sel_arg_range_seq_init
    initialises stack[0] as NOT a key part
  / sel_arg_range_seq_next
    iterates through the key parts, adding key part n to stack[n+1]

key part #32 gets referenced by step_down_to(), setting seq->i off the
end of the array.

Fix: RANGE_SEQ_ENTRY stack[MAX_REF_PARTS+1];

The above change exposed an issue with key length calculation on
MS Windows.  Calling make_prev_keypart_map(32) caused the resultant
bitmap to be calculated as (1UL << 32) - 1.  Using the MSVC compiler
this resulted in an empty key length calculation during
handler::index_read_map, causing an assertion in ha_innobase::index_read().

As we only need 32 bits to represent our key map, we change the type thus
-typedef ulong key_part_map;
+typedef uint32 key_part_map;

We correct make_keypart_map() and make_prev_keypart_map() to call our
overflow safe my_set_bits().  We also correct bka_range_seq_next()
and bkah_range_seq_next() to use make_prev_keypart_map().

We also add some DBUG_ASSERTS in key_part_map processing elsewhere,
exposing some issues in our BNLH implementation.  We cap the number of
keyuse parts here, altering the explain output of 2 of our tests.

Numerous places needed bit shift operations altered to use
make*keymap_part and various format strings needed to be corrected.
Daniel Black
Merge branch '11.4' into 11.4-MDEV-40123
Sergei Golubchik
Revert "MDEV-36832 UPDATE...IN(SELECT) acquires spurious gap locks on FK index"

This reverts commit f4a3b69bdf14. As agreed with the contributor.
It breaks 11.4.
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]>
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-25176 Shutdown hangs if event scheduler is started during shutdown

SET GLOBAL event_scheduler=1 executed by a connection during shutdown
could start the scheduler thread after close_connections() called
Events::stop(). Nothing stops this thread and close_connections()
waits for it forever.

Now it hangs instead of a crash since MDEV-30260 fix: it moved
deinit() from close_connections() to clean_up(), so the scheduler is
not freed under the running thread anymore.

The fix makes Event_scheduler::start() do nothing when abort_loop is
set. abort_loop is set before close_connections() and is checked under
LOCK_scheduler_state, which stop() also takes, so the scheduler is
either started before stop() and stopped by it, or not started at all.
No error needed: the server is shutting down.
Oleksandr Byelkin
MDEV-32401 expression cache lead to crash if table of wrong type created and the cache switched off

1) take into account TMP_TABLE_ALL_COLUMNS when
  we are modifying agg_item->result_field
2) remove unused now "bool materialized_subquery;"

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Aleksey Midenkov
MDEV-41543 Changing INTERVAL of SYSTEM_TIME partitioning does not move history

ALTER TABLE ... PARTITION BY SYSTEM_TIME with a changed INTERVAL or
STARTS on a table already partitioned by SYSTEM_TIME took the fast
ALTER path, which only rewrites the table definition. The history rows
stayed where the old layout put them, so after the ALTER they were in
wrong partitions. An unchanged interval took the copy path instead.

MDEV-29873 replaced memcmp() of the intervals, which is true when they
differ, with interval_t::operator==, which is true when they are equal,
and lost the negation.

The copy path was also broken: it assigned the whole vers_info of the
new partitioning spec to the cloned partition info, now_part and
hist_part included. The ALTER does not list partitions, so now_part
became NULL and check_partition_info() failed with ER_VERS_WRONG_PARTS
for a table with explicit partitions (MDEV-33370 test case).

The fix negates the comparison again (now with interval_t::operator!=),
so a changed interval rebuilds the table and redistributes the history.
It copies only interval, limit and auto_hist from the new spec and keeps
now_part and hist_part of the existing partitions.

Without STARTS the start of the interval defaults to the current time
rounded down to the INTERVAL unit. So ALTER with the same INTERVAL and
no STARTS usually gets a different start and now rebuilds the table.

Vers_part_info::operator=, which copied now_part and hist_part and had
no other callers, is deleted.

Fast ALTER was also chosen when the same statement changed the table
definition, e.g. ADD COLUMN with the same INTERVAL and STARTS, or DROP
COLUMN with LIMIT. It wrote the new .frm, but the partitions kept the
old record layout. Now any change of the table definition
(alter_info->flags) takes the copy path.