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
Sergei Golubchik
ER_OUT_OF_SORTMEMORY should not be ME_ERROR_LOG+ME_FATAL

it's not OOM, it's "filesort requires more memory than a user specified
session local limit". Not a hardware limitation, but something
an unprivileged user configured in her own session (so, shouldn't
be ME_ERROR_LOG). And unlike true low-memory situation this error
condition doesn't affect following statements (so, shouldn't be ME_FATAL)
Daniel Black
MDEV-40386 enable duckdb tests for MSAN
Oleksandr Byelkin
MDEV-41099 HANDLER READ missing column privilege check

HANDLER OPEN accepted column-level SELECT grants as table access, but
HANDLER READ returns all columns and never checked column privileges.
Reopen of a handler table (after FLUSH/ALTER) did no checks at all.

Require SELECT on every column (as for SELECT *) when the user has no
table-level SELECT, and redo the privilege checks on reopen.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
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
Maximilian Krög
MDEV-40417 A column with compression enabled automatically adds DEFAULT ''

Compression is stored in unireg_check as Field::TMYSQL_COMPRESSED, but
has_default_function() treated any unireg_check other than Field::NONE as a
default function.  A COMPRESSED NOT NULL column without an explicit DEFAULT
therefore never got NO_DEFAULT_VALUE_FLAG, the FRM was written without
FIELDFLAG_NO_DEFAULT, and the column silently became optional while
SHOW CREATE TABLE displayed a phantom DEFAULT ''.

Exclude TMYSQL_COMPRESSED in has_default_function() and use that method in
Column_definition::check() as well, so that both places which set
NO_DEFAULT_VALUE_FLAG stay in sync.

Tables created before the fix keep the wrong implicit DEFAULT '' in their
FRM and are not repaired automatically, the affected columns need an
explicit ALTER TABLE ... MODIFY.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
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.
forkfun
MDEV-39146 Fix ASAN use-after-free races on THD::security_ctx

Event_job_data::execute() pointed thd->security_ctx at a Security_context
local to itself. A concurrent PROCESSLIST scan can capture that pointer
unlocked and dereference it after execute() returns, freeing the stack
frame it pointed into.

Move the Security_context into Event_job_data itself (a stack local of
Event_worker_thread::run(), which outlives thd's own deletion), so it
stays valid for as long as thd can be.
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.
PranavKTiwari
MDEV-39245: Added ASCII validation at two points using my_string_repertoire():

1. Built-in plugins (plugin_init):
  A non-ASCII builtin name is a developer error. Added a check
  using my_string_repertoire() that prints an error via
  print_init_failed_error() and returns 1 to abort server startup.

2. Dynamically loaded plugins (plugin_add):
  Added a pre-validation loop before the registration loop. If any
  plugin name in the .so is non-ASCII, the entire .so is rejected
  before any plugin is registered, preventing partial state where
  valid plugins from the same .so get left INACTIVE in the hash.

Added test plugins and MTR tests to verify both rejection of
non-ASCII named plugins and successful loading of ASCII named plugins.
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-40311 Fix mysqldump-nl leaving slave connection behind

The trailing CHANGE MASTER left master.info in the datadir, so a
later test that restarts the server auto-started the slave and broke
its check-testcase. Use RESET SLAVE ALL to drop the connection.

MTR's internal check of the test case 'sys_vars.default_master_connection_basic' failed.
This means that the test case does not preserve the state that existed
before the test case was executed.  Most likely the test case did not
do a proper clean-up. It could also be caused by the previous test run
by this thread, if the server wasn't restarted.
This is the diff of the states of the servers before and after the
test case was executed:
-Slave_IO_Running No
-Slave_SQL_Running No
+Slave_IO_Running Connecting
+Slave_SQL_Running Yes
...
-Last_IO_Errno 0
-Last_IO_Error
+Last_IO_Errno 1045
+Last_IO_Error error connecting to master '[email protected]:3306' - retry-time: 60  maximum-retries: 100000  message: Access denied for user 'root'@'localhost' (using password: NO)
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.
Khaled Riyad
MDEV-40377 Change Server source code to point to new docs (10.11 part)

Replace the remaining Knowledge Base links with their MariaDB
Documentation equivalents, and fix the 14 help table URLs pointing at
/README pages that do not exist. Only URLs change in
fill_help_tables.sql.

Merging upward: fill_help_tables.sql conflicts at 10.11->11.4 and
11.8->12.3. At those two merges keep the target branch's version,
since 11.4, 11.8 and 12.3 each carry their own URL fix. From 12.3 to
13.1 and 13.1 to main it merges cleanly; take the incoming change.
.github/pull_request_template.md is deleted in 12.3; keep the deletion.
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
Khaled Riyad
MDEV-41408 MTR prepared statement protocol skipping statements starting with '('

With --ps-protocol, mysqltest runs a SELECT a second time and compares
the results. The regex ps2_re only matched a leading SELECT, so a
statement starting with '(' was executed only once.

Allow any number of '(', each optionally followed by spaces, before
SELECT in ps2_re.
PranavKTiwari
MDEV-28610 : Assertion  marked_for_read() failed upon range select with virtual column in index.
Problem:
Executing a range select using an index that includes virtual/generated columns
(e.g. SELECT ... WHERE c BETWEEN ... ORDER BY d) could trigger:

Assertion 'marked_for_read()' failed in Field access during execution.

Cause:
The keyread initialization path was populating table->read_set using
mark_index_columns(), which follows the non-recursive index marking path.
This only marks direct index fields and does not resolve dependencies of
virtual/generated columns.

As a result, when an index contained virtual columns, their dependent base
columns were not included in read_set, leading to invalid access during
later evaluation of virtual columns.

Fix:
Replace mark_index_columns() with mark_index_columns_for_read() in the
keyread initialization path. This ensures the recursive read-marking logic is
used, so virtual/generated column dependencies are correctly propagated into
read_set before execution.
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.
Marko Mäkelä
Merge 11.4 into 11.8
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]>
Marko Mäkelä
MDEV-41318 Incorrect recovery of FILE_CREATE after FILE_RENAME

recv_recovery_from_checkpoint_start(): Before applying any page-level
log records by invoking recv_scan_log(true, parser), invoke
recv_rename_files() to replay FILE_RENAME records. In this way,
recv_sys_t::recover_deferred() will not overwrite any old data files
that had been renamed before a new file was created.

recv_sys_t::validate_checkpoint(): Refer to recv_sys.scanned_lsn
rather than recv_sys.lsn, because recv_scan_log(false, parser)
may reset the latter to rewound_lsn in case we run out of memory for
recv_sys.pages. In any case, the second call to recv_scan_log() will
proceed to the end of the log and parse all records.

Reviewed by: Thirunarayanan Balathandayuthapani
Vladislav Vaintroub
MDEV-28746 follow-up: missed relative paths overflowing MAX_PATH

my_win_sopen() only checked the length of the raw path it was given, but
the server opens table files via paths relative to its data directory,
so a short relative path can still overflow MAX_PATH once
resolved against a long enough datadir. That case was misreported as
ER_BAD_DB_ERROR instead of ER_CANT_CREATE_TABLE/ENAMETOOLONG.

Resolve the path via GetFullPathName() before deciding whether the path
was too long, factored into resolved_path_too_long(). A failed resolve
is only treated as too-long when GetLastError() is
ERROR_FILENAME_EXCED_RANGE, so unrelated resolution failures keep
mapping to the original CreateFile error.

Also fix the global errtable mapping of ERROR_FILENAME_EXCED_RANGE: it
was mapped to ENOENT, so any Win32 call that got that error code
directly (not via ERROR_PATH_NOT_FOUND) was misreported the same way.

Assisted-by: Claude:claude-sonnet-5
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.
Sergei Golubchik
Merge branch '10.11' into 11.4
PranavKTiwari
MDEV-30297 Server crash / assertion failure in Compare_identifiers::operator upon dropping period with empty name

Problem:
ALTER TABLE ... DROP PERIOD IF EXISTS FOR can trigger an assertion failure in debug builds and crash in non-debug builds.

Cause:
Lex_cstring_with_compare::streq() may invoke Compare_identifiers on default-constructed Lex_cstring objects (str == NULL, length == 0). Compare_identifiers assumes non-null string pointers and asserts or crashes when called with a null pointer.

Fix:
Add null-pointer handling to Lex_cstring_with_compare::streq() and avoid calling Compare_identifiers when either string pointer is null. This prevents invalid comparisons while preserving existing behavior for initialized strings.
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]>
Jan Lindström
MDEV-41073: server aborts after "Unknown error" is logged for FK key exceeding 3500

Failure:
- wsrep_rec_get_foreign_key() returned DB_ERROR when a write set key
  exceeded WSREP_MAX_SUPPORTED_KEY_LENGTH; the caller does not know
  DB_ERROR and calls ib::fatal().
- wsrep_fk_key_space_left() needed two bytes for a NULL column instead
  of one; only the flag byte is ever written for NULL.
- Cutting a whole number, float or double to fit the remaining buffer
  produces a different value, not a shorter one, and for a float or
  double not even a valid one: mach_float_read()/mach_double_read()
  read a fixed 4 or 8 bytes regardless, past an assertion in a debug
  build and past the buffer itself in a release one.
- wsrep_store_key_val_for_row()'s equivalent fixed-length branch had
  the same unchecked copy, reachable only in theory given InnoDB's own
  index length limit, but inconsistent with every other branch in that
  function.
- The same function normalized a VARCHAR column's collation weights up
  to 3072 bytes while wsrep_rec_get_foreign_key() normalized it up to
  3500, so the two produced a different key for a value whose
  normalized form falls between the two limits.
- wsrep_store_key_val_for_row() kept iterating columns after one did
  not fit, relying on every later branch clamping to zero rather than
  stopping outright.
- MW-292 matched its two debug sync waiters by substring, not an exact
  match, independent of wait order.

Fix:
- wsrep_rec_get_foreign_key() now cuts the key the same way
  wsrep_store_key_val_for_row() does, reports the cut as a warning
  (ER_TOO_LONG_KEY under strict mode), and returns DB_TOO_BIG_RECORD.
- wsrep_fk_key_space_left() takes a fixed_len flag: a whole number,
  float or double must fit in full or is left out of the key entirely,
  the same way a value that does not fit even one byte already was.
- wsrep_store_key_val_for_row() applies the same all-or-nothing rule to
  its own fixed-length branch, reusing get_innobase_type_from_mysql_type()
  so both functions agree on which types that covers, and now stops
  storing further columns as soon as one does not fit, in every branch.
- wsrep_store_key_val_for_row()'s VARCHAR branch normalizes up to
  WSREP_MAX_SUPPORTED_KEY_LENGTH, matching wsrep_rec_get_foreign_key(),
  with its buffer grown to match.

Test:
- galera_ws_datatypes.test and galera_ws_datatypes_plugin.test cover
  every MariaDB data type in a primary key, unique key, plain key and
  foreign key (referencing a primary or unique key), including NULL
  foreign key columns.
- galera_ws_datatypes_fixed_length.test covers a foreign key column cut
  to fewer bytes than a whole number, float or double needs.
- galera_ws_datatypes_varchar_cap.test covers a VARCHAR foreign key
  column whose normalized form falls between the two limits above.

Assisted-by: https://mariadb.org/governance/governance-ai-policy/
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.
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.
PranavKTiwari
MDEV-26820 Assertion 'marked_for_read()' failed upon SELECT with VALUE(virtual column)
Problem:
Item_insert_value::fix_fields() created a temporary field
without preserving vcol_info. As a result, VALUE()/VALUES()
on virtual columns lost dependency metadata and could trigger:

Assertion `marked_for_read()' failed during virtual column evaluation.

Cause:
The temporary Field_string copied field_index but did not copy virtual column metadata from the original field.

Fix:
Preserve vcol_info when creating temporary fields in Item_insert_value::fix_fields() so virtual column dependency
tracking remains intact.
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.
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.
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
Rex Johnston
MDEV-41225 Parse the ORDER BY tail of a wrapped parenthesized query in the wrapping select

A parenthesized query expression that already has its own ORDER BY or
LIMIT and is followed by another ORDER BY, e.g.

  (SELECT c1 FROM t1 ORDER BY c1 LIMIT 2) ORDER BY <expr> LIMIT 1

is wrapped into a derived table, and the outer ORDER BY/LIMIT is attached
to the wrapping select.  The grammar pushed the inner select before
parsing the tail, and add_tail_to_query_expression_body_ext_parens()
created the wrapper only after the tail had been parsed.  Anything that
is attached to the current select while the tail is being parsed was
therefore attached to the inner select, while the ORDER BY list itself
was moved to the wrapper:

- Window functions and their window specs were added to the inner
  select's window_funcs/window_specs.  The same Item_window_func was then
  in the wrapper's ORDER BY and in the inner select's window function
  list, which triggers the original assertion reported in MDEV-41225.

  (SELECT 1 FROM t1 LIMIT 1)
    ORDER BY PERCENTILE_DISC(1) WITHIN GROUP(ORDER BY TIME'0') OVER();

  The function is computed by the inner select over the rows before its
  LIMIT, so the outer ORDER BY sorts on wrong values
  (e.g. COUNT(*) OVER () returned 3 for a 2-row result).

- Subqueries were registered as units of the inner select.  An
  uncorrelated subquery in the tail crashed the server with SIGSEGV when
  it was executed by the outer filesort.  A correlated one resolved its
  outer references in the inner select (t1.c1) instead of the derived
  table.

The decision to wrap depends only on whether the inner select already
has a tail and on whether the outer tail has ORDER BY.  LIMIT and locking
clauses cannot contain window functions or subqueries.
We replace query_expression_tail with
query_expression_tail_with_order and query_expression_tail_no_order
so the mid-rule action knows whether an ORDER BY follows.
The new LEX::push_select_for_ext_parens_tail() creates the wrapper before
an ORDER BY tail is parsed when wrapping is required, and pushes it instead
of the inner select.  The tail's items are then created in the wrapper's
context, and window functions and subqueries are attached to the wrapper.
add_tail_to_query_expression_body_ext_parens() takes the pushed select and
skips wrapping when it has already happened; the other cases keep the
previous logic.  The grammar has the same number of conflicts as before.

A subquery in such a tail can no longer refer to the tables of the wrapped
query expression (e.g. t1.c1 above) and gets ER_BAD_FIELD_ERROR,
as those tables are not visible outside the derived table.

This commit was prepared with Claude Code (Opus 5.5). It traced the
wrong-result and crash cases to the parse-time registration of window
functions and subqueries in the inner select, tested the grammar split
with bison, wrote the code change and the brackets test.
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 whole header at once, so one vio_read() for the
16-byte part and one for the trailing part (if any, it is empty for
the LOCAL command) is enough, a short read means a truncated header.

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
(connect_tcp() is shared with proxy_send_handshake_error()).

Assisted-by: Claude:claude-sonnet-5-5