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
Marko Mäkelä
MDEV-40070 innodb_log_archive multi-batch recovery crash

recv_sys_t::parse_mmap(): When the current mini-transaction spans two
log files and we run out of memory while attempting to store the parsed
records into recv_sys.pages, the next log file would already have been
closed by recv_sys_t::rewind(). Handle this condition specially.
Monty
MDEV-40029 Add support for bit fields to HEAP

This adds support for BIT_FIELD in record and keys for HEAP tables.

The HEAP engine now has HA_CAN_BIT_FIELD set in table_flags()

Multiple bugs in BIT field handling was found fixed. Some in HEAP table
code, other bugs was affecting usage of BIT fields as keys.
ParadoxV5
[skip ci] MDEV-38972: preliminarily reörganize in one `.h`–`.cc` pair

This commit forcibly reörganizes the contents in the `rpl_info_file.h`
trio of header-only files to one `rpl_info_file.h` for declarations and
one `rpl_info_file.cc` for long definitions.

Due to the files’ extensive use of C++ templates, compiling at this
commit _will_ fail with “undefined reference” linker errors.
Rather, this incomplete migration commit intends to avoid muddying the
following commits’ refactors to this relocation.

The only other change in this commit is the omission of pre-C++17 stubs
used by RocksDB, as they’re obsolete since MDEV-38213 and shall be
wiped as a part of MDEV-35462.
Alexander Barkov
MDEV-39587 Package-wide TYPE for variable declarations

SET sql_mode=ORACLE;
DELIMITER $$
CREATE OR REPLACE PACKAGE pkg AS
  -- Declare a package public data type
  TYPE varchar_array IS TABLE OF VARCHAR(2000) INDEX BY INTEGER;
END;
$$
DELIMITER ;
DELIMITER $$

CREATE OR REPLACE PROCEDURE p1 AS
  v pkg.varchar_array; -- Use the package public data type
BEGIN
  v(0):='test';
  SELECT v(0);
END;
$$
DELIMITER ;

Note, the change is done only for sql_mode=ORACLE, because the TYPE
declaration is not available for the default mode.

Where package-wide types are available
--------------------------------------
- Variabe list type:
    DECLARE var pkg1.type1;

- RETURN type for a package routine:
    CREATE FUNCTION .. RETURN pkg1.type1 ...

- Parameter type for a package routine:
    PROCEDURE p1(param1 pkg1.type1);

- Assoc array element type:
    TYPE assoc1_t IS TABLE OF pkg1.type1 ...

- REF CURSOR RETURN type:
    TYPE cur1_t IS REF CURSOR RETURN pkg1.type1;

Change details
--------------

- Adding a member Lex_length_and_dec_st::m_foreign_module_type
  It's set to true when the data type was initialized from a TYPE
  in foreign routine (e.g. in PACKAGE spec).
  It's needed to prevent use of qualified identifiers in public contexts,
  i.e. in schema public routine parameter types and schema publuc function
  RETURN types.
  Adding a helper method sp_head::check_applicability() which prevents
  use of qualified types in public context.

- Adding a helper method sp_head::raise_unknown_data_type().

- Adding methods LEX::set_field_type_typedef_package_spec() for
  2-step and 3-step qualified indentifiers.
  It's used in field_type_all_with_typedefs which covers cases:
  - Variabe list type        : DECLARE var pkg1.type1;
  - RETURN type              : CREATE FUNCTION .. RETURN pkg1.type1 ...
  - Parameter type          : PROCEDURE p1(param1 pkg1.type1);
  - Assoc array element type : TYPE assoc1_t IS TABLE OF pkg1.type1 ...

- Adding a method LEX::declare_type_ref_cursor_return_typedef().
  It handles cases when a new TYPE REF CURSOR RETURN is declared,
  for both for qualified RETURN types and non-qualified RETURN types:
  - TYPE cur0_t IS REF CURSOR RETURN rec1_t;
  - TYPE cur0_t IS REF CURSOR RETURN pkg1.rec1_t;
  - TYPE cur0_t IS REF CURSOR RETURN db1.pkg1.rec1_t;

  The code was moved from LEX::declare_type_ref_cursor() into
  LEX::declare_type_ref_cursor_return_typedef() and extended
  to cover qualified RETURN types.

- Adding a method Sql_path::find_package_spec_type().
  It iterates through all schemas specified in @@path and searches
  for the given type in the given package.

- Adding a helper method sp_pcontext::type_defs_add_ref_cursor()
  to reuse the code.

- Adding a new method sp_package::get_typedef() to search
  for TYPE definitions in PACKAGE specifications.

- Adding a new method sp_head::get_typedef_package_spec()
  to search for TYPE definitions used by a PROCEDURE or FUNCTION.

- Adding a helper method
    Sp_handler::sp_cache_routine_reentrant_suppress_errors
  Adding a method Sp_handler::find_package_spec().
Marko Mäkelä
Minor cleanup
Marko Mäkelä
Remove insufficient locking on Apple
Sergei Golubchik
update test results
Rex Johnston
MDEV-39499 Updates to derived-with-keys, window functions determining

..records per key

Enabling derived keys optimization for derived.col = const pushed
conditions.

Estimating records per key in derived key for the optimizer
based on form and/or size of components of a derived table.

Consider any derived table of the form

SELECT ..., ROW_NUMBER ()  OVER (PARTITION BY c1,c2 order by ...)
FROM t1, t2, t3 ...
WHERE ...

If the optimizer generates a key on this derived table because of
a constraint being pushed into it, it currently will not consider key
components of the form  col = const

We lift this constraint and add code to TABLE::add_tmp_key to search
for a window function ROW_NUMBER().  From the partition list c1, c2 we
can in infer an estimate of the number of rows we expect to see for
each key value.  In the absence of EITS, we still have an number of
expected records in our referred to table and will fall back to using
that as a worst case scenario.

As a consequence of forcing best_access_path to now consider a generated
index's records per key on any type of derived table, we see a number of
optimization changes, for example a range optimizer might now be
considered best and might return IMPOSSIBLE_RANGE (seen in
rowid_filter_myisam.result).
Marko Mäkelä
ustar_zeropad(): Wrap strncpy() to silence GCC -Wstringop-truncation
Eric
MDEV-38144: update Optional_metadata_fields to use MariaDB types

Currently Optional_metadata_fields has many members that use classes
from the C++ standard library, most notably the use of std::vector and
std::string. This is inconsistent with the coding standards, as MariaDB
defines its own types for arrays/lists/strings. This patch updates
these variables to use existing MariaDB types.

Additionally, the structure of the fields is changed. Instead of having
a separate list to track each metadata field; the structure now exists
at the column level (Column_metadata), and it has individual member
variables to describe its metadata. This allows for more
straightforward memory management, as everything will now be allocated
at once.

There is also a bug fix in this patch. Prior to this refactor, YEAR
columns would not consume their "unsigned" bit flag, resulting in
numeric columns after a YEAR type to have incorrect signage. This is
now fixed.

Reviewed-by: Brandon Nesterenko <[email protected]>
Alessandro Vetere
PERF-475 Use per-cell latch in lock_move_reorganize_page()

lock_move_reorganize_page() was acquiring lock_sys.latch in exclusive
mode (via LockMutexGuard) for the entire body of phase 2 (lock chain
iteration, bitmap reset, and lock_rec_add_to_queue() calls). The
function however only touches record locks belonging to a single page,
which all live in a single lock_sys.rec_hash cell. Holding that cell
latch in exclusive mode via LockGuard is sufficient:

- The cell latch protects the cell's lock chain and the bitmaps of the
  lock_t objects in it (lock_rec_bitmap_reset and the new bit set by
  lock_rec_add_to_queue()).
- It also protects lock->type_mode, including the LOCK_WAIT bit. The
  canonical clear in lock_reset_lock_and_trx_wait() runs under the cell
  latch, and lock_grant() invokes it before taking trx->mutex, so the bit
  is cell-latch state rather than trx->mutex state. Phase 1 only clears
  the bit and leaves trx->lock.wait_lock intact; the copy in old_locks
  keeps LOCK_WAIT and phase 2 re-adds the lock with it, so the wait
  relationship (guarded by lock_sys.wait_mutex) is preserved across the
  move. Neither trx->mutex nor wait_mutex is required here.
- Each owning trx's mutex is acquired per-iteration to protect that trx's
  trx_locks list and lock_heap during lock_rec_add_to_queue().

The global exclusive latch was over-strong: it blocked every concurrent
lock_sys.rd_lock() acquirer in lock_rec_lock() and lock_table()
server-wide for the duration of the reorganize, contributing
disproportionately to the lock_sys.latch convoy under heavy concurrency.

The TMLockGuard fast-path empty check at the top of the function is
preserved; for cells with no locks the cost is still just a TSX-elided
read.
Rex Johnston
MDEV-40012  start cleanup of claude's worker side multi-table join

Attached standalone functions to their obvious object, DBUG_ tracing in
functions that clearly need it, NOT FINISHED.

Looks to me like the buffering code where the worker has finished it's
part of the join and writes it's output in chunks doesn't work properly.
Probably not relevant as this whole buffering needs to be sidestepped.
Rucha Deodhar
MDEV-34723: NEW and OLD in a trigger as row variables

Implementation:
NEW and OLD represent the entire table row. So it can be thought of as
list of Item_trigger_field. When we are in a trigger and NEW or OLD is
encountered, create Item_trigger_row object with same constructor as
Item_trigger_field, it will also be used later while creating
Item_trigger_field objects. Populate the m_fields list while
fixing fields. Create a corresponding instruction sp_instr_set_trigger_row
which will be used to set the values
Abdelrahman Hedia
MDEV-28213 Skip ignored domain IDs during GTID validation

When a slave is configured with IGNORE_DOMAIN_IDS or DO_DOMAIN_IDS,
the master's binlog dump thread should skip GTID state validation for
those filtered domains. This avoids false ER_GTID_POSITION_NOT_FOUND
errors when the slave does not have (or need) the current GTID state
for domains it is filtering.

Before sending COM_BINLOG_DUMP, the slave now tells the master which
domains it filters by setting a user variable. Only one of
IGNORE_DOMAIN_IDS or DO_DOMAIN_IDS can be active at a time, so the slave
sends just the configured list through either
@slave_connect_state_domain_ids_ignore or
@slave_connect_state_domain_ids_do. The master parses the list into a
Domain_id_filter attached to the slave_connection_state and consults it
while locating the binlog file and validating the slave start position.

Using a user variable keeps this backwards compatible: an older master
simply stores the unknown variable and ignores it, and an older slave
never sends it (the filter stays NULL and every domain is validated as
before).

Changes:
- sql/slave.cc: in get_master_version_and_clock(), figure out which of
  IGNORE_DOMAIN_IDS / DO_DOMAIN_IDS is configured and send that single
  list to the master. Add build_domain_ids_query() to format the
  "SET @<var>='id1,id2,...'" statement.
- sql/sql_repl.cc: in init_binlog_sender(), read the slave's user
  variable (get_user_var_string()), lazily allocate a Domain_id_filter,
  parse the comma-separated ids (load_domain_ids_from_string()) and sort
  them. Skip filtered domains in contains_all_slave_gtid(),
  check_slave_start_position(), gtid_find_binlog_pos() and
  gtid_find_engine_pos(), and document the behaviour at
  gtid_check_binlog_file().
- sql/rpl_gtid.cc: skip filtered domains in
  rpl_binlog_state_base::is_before_pos(); initialise and delete the
  domain_filter in slave_connection_state's constructor/destructor.
- sql/rpl_gtid.h: add the Domain_id_filter *domain_filter member to
  slave_connection_state (under HAVE_REPLICATION).
- sql/rpl_mi.h, sql/rpl_mi.cc: add the Domain_id_filter::var_name_ignore
  and var_name_do user-variable name constants.
- include/rpl_gtid_base.h: forward-declare Domain_id_filter.
- mysql-test/suite/rpl/t/rpl_gtid_ignored_domain_ids_validation.test,
  mysql-test/suite/rpl/r/rpl_gtid_ignored_domain_ids_validation.result:
  new test covering IGNORE_DOMAIN_IDS and DO_DOMAIN_IDS with purged
  binlogs.

Reviewed-by: Georgi Kodinov <[email protected]>
Reviewed-by: Brandon Nesterenko <[email protected]>
Alexander Barkov
MDEV-39587 Package-wide TYPE for variable declarations

SET sql_mode=ORACLE;
DELIMITER $$
CREATE OR REPLACE PACKAGE pkg AS
  -- Declare a package public data type
  TYPE varchar_array IS TABLE OF VARCHAR(2000) INDEX BY INTEGER;
END;
$$
DELIMITER ;
DELIMITER $$

CREATE OR REPLACE PROCEDURE p1 AS
  v pkg.varchar_array; -- Use the package public data type
BEGIN
  v(0):='test';
  SELECT v(0);
END;
$$
DELIMITER ;

Note, the change is done only for sql_mode=ORACLE, because the TYPE
declaration is not available for the default mode.

Where package-wide types are available
--------------------------------------
- Variabe list type:
    DECLARE var pkg1.type1;

- RETURN type for a package routine:
    CREATE FUNCTION .. RETURN pkg1.type1 ...

- Parameter type for a package routine:
    PROCEDURE p1(param1 pkg1.type1);

- Assoc array element type:
    TYPE assoc1_t IS TABLE OF pkg1.type1 ...

- REF CURSOR RETURN type:
    TYPE cur1_t IS REF CURSOR RETURN pkg1.type1;

Change details
--------------

- Adding a member Lex_length_and_dec_st::m_foreign_module_type
  It's set to true when the data type was initialized from a TYPE
  in foreign routine (e.g. in PACKAGE spec).
  It's needed to prevent use of qualified identifiers in public contexts,
  i.e. in schema public routine parameter types and schema publuc function
  RETURN types.
  Adding a helper method sp_head::check_applicability() which prevents
  use of qualified types in public context.

- Adding a helper method sp_head::raise_unknown_data_type().

- Adding methods LEX::set_field_type_typedef_package_spec() for
  2-step and 3-step qualified indentifiers.
  It's used in field_type_all_with_typedefs which covers cases:
  - Variabe list type        : DECLARE var pkg1.type1;
  - RETURN type              : CREATE FUNCTION .. RETURN pkg1.type1 ...
  - Parameter type          : PROCEDURE p1(param1 pkg1.type1);
  - Assoc array element type : TYPE assoc1_t IS TABLE OF pkg1.type1 ...

- Adding a method LEX::declare_type_ref_cursor_return_typedef().
  It handles cases when a new TYPE REF CURSOR RETURN is declared,
  for both for qualified RETURN types and non-qualified RETURN types:
  - TYPE cur0_t IS REF CURSOR RETURN rec1_t;
  - TYPE cur0_t IS REF CURSOR RETURN pkg1.rec1_t;
  - TYPE cur0_t IS REF CURSOR RETURN db1.pkg1.rec1_t;

  The code was moved from LEX::declare_type_ref_cursor() into
  LEX::declare_type_ref_cursor_return_typedef() and extended
  to cover qualified RETURN types.

- Adding a method Sql_path::find_package_spec_type().
  It iterates through all schemas specified in @@path and searches
  for the given type in the given package.

- Adding a helper method sp_pcontext::type_defs_add_ref_cursor()
  to reuse the code.

- Adding a new method sp_package::get_typedef() to search
  for TYPE definitions in PACKAGE specifications.

- Adding a new method sp_head::get_typedef_package_spec()
  to search for TYPE definitions used by a PROCEDURE or FUNCTION.

- Adding a helper method
    Sp_handler::sp_cache_routine_reentrant_suppress_errors
  Adding a method Sp_handler::find_package_spec().
Vladislav Vaintroub
Appveyor CI - use VS2026 image

Also, remove before_build logic trying to determine if newer commit on the
same branch exists. This takes a lot of time on outdated repos.

The same effect can be done by reducing the clone_depth to 1.
It will fail if newer commits exist, and is actually prefered - the amount
of pushes grew significantly in last time, thus fail-faster is a better
strategy to reduce build queue length.
Fariha Shaikh
MDEV-38936 Proactive handling of InnoDB tablespace full condition

InnoDB write failures occur when tablespace files exceed filesystem size
limits. Current behavior logs errors but continues accepting
transactions, causing repeated failures and potential data integrity
issues.

Add proactive monitoring by emitting warnings when InnoDB tablespaces
approach a configurable size threshold.

Key features:
- Two new system variables:
  * innodb_tablespace_size_warning_threshold (default 0, disabled):
    Maximum tablespace size in bytes before warnings begin
  * innodb_tablespace_size_warning_pct (default 85%): Percentage of
    threshold at which to start emitting warnings
- Warning frequency:
  * Below warning_pct: No warnings
  * At or above warning_pct: Every 1% increase (85%, 86%, 87%, etc.)
- Per-tablespace tracking with automatic reset on TRUNCATE/DROP or
  threshold/percentage changes
- Zero overhead when threshold is 0
- Progressive warnings capped at 100%

Implementation adds fil_space_t::extend() which consolidates file
extension, size_in_header update, and size warning checks.
Per-tablespace warning state is tracked in fil_space_t
(m_last_size_warning_pct, m_last_warning_threshold, m_last_warning_pct).

All new code of the whole pull request, including one or several files
that are either new files or modified ones, are contributed under the
BSD-new license. I am contributing on behalf of my employer Amazon Web
Services, Inc.
Alessandro Vetere
PERF-475 Reduce contention on lock_sys.latch

The trylock attempts on per-cell lock_sys_t::hash_latch (try_acquire())
and on per-table dict_table_t::lock_mutex_trylock() inside
lock_release_try(), lock_release_on_prepare_try() and
lock_rec_unlock_unmodified() now use a bounded spin loop
(LOCK_RELEASE_TRY_SPIN_BUDGET iterations of CAS + MY_RELAX_CPU())
instead of a single CAS attempt.

These paths hold trx->mutex while attempting the trylock, which is the
reverse of the standard order used by lock_rec_convert_impl_to_expl().
Blocking acquisition is therefore unsafe, hence the trylock pattern.
However, a single failed CAS marks the entire pass of lock_release_try()
as unsuccessful, and after 5 such failed passes lock_release() falls
back to exclusive lock_sys.wr_lock() for the whole transaction. That
global wr_lock then blocks every concurrent lock_sys.rd_lock() acquirer
in lock_rec_lock() and lock_table(), producing a server-wide convoy
under heavy concurrency.

The bounded spin (no syscall, no blocking) gives a transient latch
holder time to release without weakening the deadlock-avoidance
guarantee that motivated the trylock pattern. The extra trx->mutex hold
time is bounded by LOCK_RELEASE_TRY_SPIN_BUDGET times the pause cost.
Ahmad
MDEV-34805 provide various information about vector indexes

Adds INFORMATION_SCHEMA.VECTOR_INDEXES table exposing statistics for MHNSW vector
indexes via a MYSQL_INFORMATION_SCHEMA_PLUGIN registered alongside
the existing mhnsw daemon plugin. columns covered:
(TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, VECTOR_DIMENSIONS,
SUBDIST_ENABLED, INDEX_SIZE, TOTAL_NODES, DELETED_ROWS,
MEMORY_SIZE, CACHE_OVERFLOWS).
Rex Johnston
MDEV-40012 Parallel Query: execute the join in the worker threads

Each parallel worker now runs the whole select-project[-join] query over
its own chunk of the driving table -- WHERE filtering, select-list
projection and the joins to the other tables -- and ships the final
result rows to the manager, which only concatenates them and sends them
to the client. This replaces the model where workers shipped raw source
records and the manager ran the join.

make_join_readinfo()'s gate (can_run_query_in_workers) chooses the
worker-side path for an inner select-project[-join] with a parallel-
scannable driving table: no tmp table (group/distinct/order/window/
buffer), no LIMIT/SQL_CALC_FOUND_ROWS/procedure/aggregate, no outer join
or semijoin, and every non-driving table reached by eq_ref/ref/full
scan. do_select() then runs run_worker_side_join() instead of the nested
loop; anything ineligible runs serially.

Each worker opens a private copy of every non-const table, deep-clones
and field-rebinds the conditions and select list, and rebuilds each ref
(clone_table_ref, mirroring create_ref_for_key). It scans its driving
chunk, runs its own inner nested loop (cp_buffer_from_ref +
ha_index_read_map / ha_index_next_same for ref/eq_ref, rnd scan
otherwise), projects each full match into a private result table and
ships the row image; the manager drains and sends.

A killed worker's own ER_QUERY_INTERRUPTED is no longer treated as a
fatal evaluation error (PWT_error_handler guards with !thd->killed) so
kills keep propagating through kill_signal with the correct kill type.

Tests: parallel_query_worker_side (single table) and parallel_query_join
(eq_ref, ref with fan-out, 3-table chain, full-scan inner table) compare
the parallel result set against serial. parallel_query / parallel_query_oom
moved to a plain SELECT (which now runs worker-side) and were re-recorded.

Co_Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
ParadoxV5
MDEV-38972: Reorganize `Info_file` entities

This commit consolidate the value structs and their related functions
to shrink the class hierarchy and mitigate many templates’s limitations.

* Rename `Persistence` to `Value_interface` and add template `Value`
* Replace subclasses with explicit specializations of the
  `Value` template’s instance methods wherever available
  * This ensures `Value` is used literally as a template – `#define`
    but typed – rather than merely for the generics as much as possible.
* Move `mariadbd_option` reference template parameter to
  `Value::default_value` pointer instance variable
* Merge DEFAULT-less classes to a case of the optional `Value`
template where the `Value::default_value` is `nullptr`
* Replace `trilean` with `std::optional<bool>` from the template
* Rename `enum_master_use_gtid::DEFAULT` to `AUTO` and *intend*
  `std::nullopt` to represent the unset/DEFAULT state for
  `Master_info_file::master_use_gtid` instead
* Dissolve `Int_IO_CACHE` to one `my_b_getsll()` (at least for now)
  and the rest merged into numeric `Value` instance methods
* Split `Master_info_file::Heartbeat_period_value`’s static methods
  to instance methods of a new `Uint32_3` conversion wrapper

Since the publication of MDEV-37530, my unimplemented designs have
evolved to feature split “metaclasses” that it can share with
`information_schema.slave_status`, especially after MDEV-31342.
As such, this commit’s redesign is modelled with a
neutral `Value::default_value` to reflect how NOT NULL
is a column constraint rather than a value property.

While here, the commit also fixes some nits in the code documentation.
Alexander Barkov
MDEV-39587 Package-wide TYPE for variable declarations

SET sql_mode=ORACLE;
DELIMITER $$
CREATE OR REPLACE PACKAGE pkg AS
  -- Declare a package public data type
  TYPE varchar_array IS TABLE OF VARCHAR(2000) INDEX BY INTEGER;
END;
$$
DELIMITER ;
DELIMITER $$

CREATE OR REPLACE PROCEDURE p1 AS
  v pkg.varchar_array; -- Use the package public data type
BEGIN
  v(0):='test';
  SELECT v(0);
END;
$$
DELIMITER ;

Note, the change is done only for sql_mode=ORACLE, because the TYPE
declaration is not available for the default mode.

Where package-wide types are available
--------------------------------------
- Variabe list type:
    DECLARE var pkg1.type1;

- RETURN type for a package routine:
    CREATE FUNCTION .. RETURN pkg1.type1 ...

- Parameter type for a package routine:
    PROCEDURE p1(param1 pkg1.type1);

- Assoc array element type:
    TYPE assoc1_t IS TABLE OF pkg1.type1 ...

- REF CURSOR RETURN type:
    TYPE cur1_t IS REF CURSOR RETURN pkg1.type1;

Change details
--------------

- Adding a member Lex_length_and_dec_st::m_foreign_module_type
  It's set to true when the data type was initialized from a TYPE
  in foreign routine (e.g. in PACKAGE spec).
  It's needed to prevent use of qualified identifiers in public contexts,
  i.e. in schema public routine parameter types and schema publuc function
  RETURN types.
  Adding a helper method sp_head::check_applicability() which prevents
  use of qualified types in public context.

- Adding a helper method sp_head::raise_unknown_data_type().

- Adding methods LEX::set_field_type_typedef_package_spec() for
  2-step and 3-step qualified indentifiers.
  It's used in field_type_all_with_typedefs which covers cases:
  - Variabe list type        : DECLARE var pkg1.type1;
  - RETURN type              : CREATE FUNCTION .. RETURN pkg1.type1 ...
  - Parameter type          : PROCEDURE p1(param1 pkg1.type1);
  - Assoc array element type : TYPE assoc1_t IS TABLE OF pkg1.type1 ...

- Adding a method LEX::declare_type_ref_cursor_return_typedef().
  It handles cases when a new TYPE REF CURSOR RETURN is declared,
  for both for qualified RETURN types and non-qualified RETURN types:
  - TYPE cur0_t IS REF CURSOR RETURN rec1_t;
  - TYPE cur0_t IS REF CURSOR RETURN pkg1.rec1_t;
  - TYPE cur0_t IS REF CURSOR RETURN db1.pkg1.rec1_t;

  The code was moved from LEX::declare_type_ref_cursor() into
  LEX::declare_type_ref_cursor_return_typedef() and extended
  to cover qualified RETURN types.

- Adding a method Sql_path::find_package_spec_type().
  It iterates through all schemas specified in @@path and searches
  for the given type in the given package.

- Adding a helper method sp_pcontext::type_defs_add_ref_cursor()
  to reuse the code.

- Adding a new method sp_package::get_typedef() to search
  for TYPE definitions in PACKAGE specifications.

- Adding a new method sp_head::get_typedef_package_spec()
  to search for TYPE definitions used by a PROCEDURE or FUNCTION.

- Adding a helper method
    Sp_handler::sp_cache_routine_reentrant_suppress_errors
  Adding a method Sp_handler::find_package_spec().
Alessandro Vetere
PERF-475 Reduce contention on lock_sys.latch

The trylock attempts on per-cell lock_sys_t::hash_latch (try_acquire())
and on per-table dict_table_t::lock_mutex_trylock() inside
lock_release_try(), lock_release_on_prepare_try() and
lock_rec_unlock_unmodified() now use a bounded spin loop
(LOCK_RELEASE_TRY_SPIN_BUDGET iterations of CAS + MY_RELAX_CPU())
instead of a single CAS attempt.

These paths hold trx->mutex while attempting the trylock, which is the
reverse of the standard order used by lock_rec_convert_impl_to_expl().
Blocking acquisition is therefore unsafe, hence the trylock pattern.
However, a single failed CAS marks the entire pass of lock_release_try()
as unsuccessful, and after 5 such failed passes lock_release() falls
back to exclusive lock_sys.wr_lock() for the whole transaction. That
global wr_lock then blocks every concurrent lock_sys.rd_lock() acquirer
in lock_rec_lock() and lock_table(), producing a server-wide convoy
under heavy concurrency.

The bounded spin (no syscall, no blocking) gives a transient latch
holder time to release without weakening the deadlock-avoidance
guarantee that motivated the trylock pattern. The extra trx->mutex hold
time is bounded by LOCK_RELEASE_TRY_SPIN_BUDGET times the pause cost.
Brandon Nesterenko
MDEV-38144: Update test results to show bug regression

The c_unsigned INT UNSIGNED would continue to show as unsigned without
the fix because the YEAR is also considered unsigned. Fixed the test to
use a signed INT after YEAR so the bug would show as the INT field
consuming the (unconsumed-by-year) UNSIGNED INT bit.

Also fixed bad spacing.
Yuchen Pei
MDEV-24813 Signal full scan to storage engines.

When starting to do a full table/index scan without a WHERE or JOIN
condition, tell the storage engine so and the corresponding
ulong-truncated LIMIT.

Include an innodb implementation: added an innodb switch
table_lock_on_full_scan, so that when the switch is on, on receiving
the full scan signal from the sql layer, if the truncated LIMIT is
ULONG_MAX (likely no LIMIT), attempt to acquire a table lock.

Updated tests that have different results with the switch on.

(Comment and code edited by Sergei Petrunia)

MDEV-24813 Drop low-value table_lock test combinations

The three deadlock_*_race tests cannot reach their DEBUG_SYNC race
under a table lock (it degenerates to a timeout), and the three I_S
tests only restate a lock-mode change already covered
by innodb_full_scan.test.

- Addressed review comments
Lawrin Novitsky
More of "uninitialized use"
ParadoxV5
MDEV-38972: Move info files’ `Value` lists to instance method init-lists

Instead of statically constructed collections of bulky member
pointer substitutes, this commit refactors them to initializer
lists of pointers prepared in a virtual instance method.

The choice of these static lists was an aggressive optimization.
Once operations reduce dependence on saving and loading, e.g., for crash
safety in non-GTID mode, that improvement will no longer be significant.
Dmitry Shulga
MDEV-40004: Server crashes in sp_head::register_instr_mem_root_for_deallocation upon shutdown

On shutdown server could crash in case triggers executed during server run
and some of triggers instructions were re-compiled.

The crash is caused by attempt to allocate a memory for storing pointers
on mem_roots used for memory allocation taken place on re-parsing failing
trigger's statements. The reason of crash is dereferencing of nullptr
returning by the function current_thd().

To fix the issue, use dummy THD on shutdown table definition cache.
Yuchen Pei
MDEV-24813 Signal full scan to storage engines.

When starting to do a full table/index scan without a WHERE or JOIN
condition, tell the storage engine so and the corresponding
ulong-truncated LIMIT.

Include an innodb implementation: added an innodb switch
table_lock_on_full_scan, so that when the switch is on, on receiving
the full scan signal from the sql layer, if the truncated LIMIT is
ULONG_MAX (likely no LIMIT), attempt to acquire a table lock.

Updated tests that have different results with the switch on.

(Comment and code edited by Sergei Petrunia)

MDEV-24813 Drop low-value table_lock test combinations

The three deadlock_*_race tests cannot reach their DEBUG_SYNC race
under a table lock (it degenerates to a timeout), and the three I_S
tests only restate a lock-mode change already covered
by innodb_full_scan.test.

- Addressed review comments
Yuchen Pei
MDEV-24813 Signal full scan to storage engines.

When starting to do a full table/index scan without a WHERE or JOIN
condition, tell the storage engine so and the corresponding
ulong-truncated LIMIT.

Include an innodb implementation: added an innodb switch
table_lock_on_full_scan, so that when the switch is on, on receiving
the full scan signal from the sql layer, if the truncated LIMIT is
ULONG_MAX (likely no LIMIT), attempt to acquire a table lock.

Updated tests that have different results with the switch on.

The three deadlock_*_race tests cannot reach their DEBUG_SYNC race
under a table lock (it degenerates to a timeout), and the three I_S
tests only restate a lock-mode change already covered
by innodb_full_scan.test.

(Comment and code edited by Sergei Petrunia <[email protected]> and
Thirunarayanan Balathandayuthapani <[email protected]>)
Yuchen Pei
MDEV-24813 Signal full scan to storage engines.

When starting to do a full table/index scan without a WHERE or JOIN
condition, tell the storage engine so and the corresponding
ulong-truncated LIMIT.

Include an innodb implementation: added an innodb switch
table_lock_on_full_scan, so that when the switch is on, on receiving
the full scan signal from the sql layer, if the truncated LIMIT is
ULONG_MAX (likely no LIMIT), attempt to acquire a table lock.

Updated tests that have different results with the switch on.

(Comment and code edited by Sergei Petrunia)

MDEV-24813 Drop low-value table_lock test combinations

The three deadlock_*_race tests cannot reach their DEBUG_SYNC race
under a table lock (it degenerates to a timeout), and the three I_S
tests only restate a lock-mode change already covered
by innodb_full_scan.test.

- Addressed review comments
Lawrin Novitsky
More of "uninitialized use"
Marko Mäkelä
MDEV-40070 innodb_log_archive multi-batch recovery crash

recv_sys_t::parse_mmap(): When the current mini-transaction spans two
log files and we run out of memory while attempting to store the parsed
records into recv_sys.pages, the next log file would already have been
closed by recv_sys_t::rewind(). Handle this condition specially.
Monty
MDEV-40030 Add support for CHECK TABLE for memory tables

CHECK TABLE is now supported, but will only return ok or fail.
Still good enough for testing heap table consistenty.
Sergei Golubchik
post-review fixes
ParadoxV5
MDEV-39482 Drop support for CHANGE MASTER savefiles from MySQL/MariaDB 5.5 and before

Remove the ugly additional code in `Info_file::load_from_file()`
for the old, inextensible format before MySQL/MariaDB 4.1 for
`@@master_info_file` and 5.6/10.0 for `@@relay_log_info_file`.

Those versions are EOL for 6 years or more,
so there’s no priority keeping a slightly divergent code
path around for them only to hinder code improvements.

MDEV-38020’s MTR test is (temporarily) removed along
with the rest of `rpl.rpl_read_old_relay_log_info`;
it will be ported to the new format in a separate commit.

While here, also replace the corresponding additional parameter for
`Info_file::save_to_file()` with an utilization of zero-initialization.
Arcadiy Ivanov
MDEV-40033 Free-list contiguous block tracking for HEAP engine

Replace the HEAP engine's O(records) per-record free-list traversal
with O(blocks) by grouping contiguous deleted records into logical
blocks. Each block uses two sentinel records (block-start at the
lowest address, block-end at the highest) to represent an arbitrarily
large contiguous group. Interior "dark" records are implicitly
covered by the block's address range and have their metadata bytes
cleared by `hp_clear_dark_records()`.

**Block metadata layout** (stored inline in deleted records):
- Byte 8 (`HP_DEL_FLAG_OFFSET`): `del_flag` -- `HP_DEL_BLOCK_START`
  (2) on the first record, `HP_DEL_BLOCK_END` (1) on the last, 0 on
  dark records and singles
- Bytes 9-10 (`HP_DEL_COUNT_OFFSET`): `uint16` block record count,
  stored only on the block-start record

**`visible` minimum** bumped from `sizeof(char*)` (8) to
`HP_DEL_METADATA_SIZE` (11) for all tables. This has zero memory
impact: `recbuffer = ALIGN(visible + 1, 8)` absorbs the shift
entirely (16 bytes for all small records).

**Delete neighbor coalescing**: `hp_push_free_block_coalesce()`
(in `hp_delete.c`) normalizes the free-list head by treating a
single record as a block of count 1, then checks adjacency in
two directions (above/below). Handles all merge cases uniformly:
single-to-single, single-to-block, block-to-single, and
block-to-block. Combined count capped at `UINT_MAX16`; falls
back to `hp_push_free_record` / `hp_push_free_block` when no
adjacency. `hp_push_free_record_coalesce()` is a thin inline
wrapper.

**Dark record clearing** is centralized in `hp_clear_dark_records`,
a strided loop that zeroes only the essential metadata bytes per
record (`del_link`, `del_flag`, `visible`) rather than the
entire `recbuffer`. Used by both `hp_push_free_block` and
`hp_push_free_block_coalesce`.

**New API in `heapdef.h`:**
- Push: `hp_push_free_record()`, `hp_push_free_block()`,
  `hp_push_free_record_coalesce()`
- Consume: `hp_pop_free_record()`, `hp_take_free_block()`
- Traverse: `hp_is_free_block_end()`, `hp_free_block_first()`,
  `hp_is_free_block_start()`, `hp_free_block_start_count()`

Non-inline functions: `hp_push_free_block()` and
`hp_push_free_block_coalesce()` in `hp_delete.c`;
`hp_take_free_block()` in `hp_write.c`.

**Caller updates:**
- `hp_delete.c`: `heap_delete()` calls
  `hp_push_free_record_coalesce()` for single-record deletes
- `hp_write.c`: error-path push and `next_free_record_pos()` pop
  use `hp_push_free_record()` / `hp_pop_free_record()`
- `hp_blob.c`: `hp_free_run_chain()` uses coalescing versions;
  `hp_take_free_list_runs()` extracted from Steps 1 and 3 of
  `hp_write_one_blob()`, parameterized by `min_avail`; blob
  allocation uses `hp_take_free_block()` / `hp_pop_free_record()`
- `hp_scan.c`: batch-skip entire deleted blocks
- `_check.c`: block-aware free-list count and scan
- `hp_shrink_tail()`: reclaims entire blocks at the tail

**Unit tests** (`hp_test_freelist-t.c`): 13 new tests (252
assertions): block formation, pop/shrink, collapse to single,
partial block take, scan batch-skip, shrink-tail with blocks,
interleaved singles and blocks, ascending/descending delete
coalescing, non-adjacent gap, coalesced block reuse by blob
insert, block-to-block via adjacent blob chains.
Dave Gosselin
MDEV-39323: CROSS JOIN query returns wrong result with NOT BETWEEN

For 1 NOT BETWEEN c0 AND c2 with c0 float and c2 int, the range
optimizer was building a SEL_TREE for only c0 > 1 and dropping the
c2 < 1 disjunct.  can_optimize_range_const rejected c2 because of
a type mismatch.

The case from the ticket returned no rows (instead of the expected six
rows) because the index range scan on c0 fetched only matches for c0 >
1 but then they were discarded by the t1.c1 = t1.c2 predicate.

Plan before the fix (range scan on c0, key_len 5):
  +----+-------+-------+------+---------+------+
  | id | table | type  | key  | key_len | rows |
  +----+-------+-------+------+---------+------+
  |  1 | t1    | range | c0  |      5 |    1 |
  |  1 | t2    | index | c0  |      6 |    3 |
  +----+-------+-------+------+---------+------+

Plan after the fix (Item_func_between::get_mm_tree returns no
usable range tree, so the optimizer falls back to using the
covering index scan on i0):
  +----+-------+-------+------+---------+------+
  | id | table | type  | key  | key_len | rows |
  +----+-------+-------+------+---------+------+
  |  1 | t2    | index | c0  |      6 |    6 |
  |  1 | t1    | index | i0  |      14 |    8 |
  +----+-------+-------+------+---------+------+

In Item_func_between::get_mm_tree, when can_optimize_range_const fails
for a range bound argument and the predicate is negated, we now
abandon the whole tree instead of continuing the loop.  The new code
mirrors the existing guard in the same function for non FIELD_ITEM
arguments.

The bug was introduced by MDEV-36235 which added
can_optimize_range_const without considering the negated path.
While we could fine tune the rejection behavior in
can_optimize_range_const, I think that should be a separate patch as
it requires careful consideration for each pair of types that could
be supplied to [NOT] BETWEEN and that's outside the scope of this
ticket (which is intended to fix the wrong result issue).

This behavior matches MySQL 9.
Alessandro Vetere
PERF-475 Use per-cell latch in lock_move_reorganize_page()

lock_move_reorganize_page() was acquiring lock_sys.latch in exclusive
mode (via LockMutexGuard) for the entire body of phase 2 (lock chain
iteration, bitmap reset, and lock_rec_add_to_queue() calls). The
function however only touches record locks belonging to a single page,
which all live in a single lock_sys.rec_hash cell. Holding that cell
latch in exclusive mode via LockGuard is sufficient:

- The cell latch protects the cell's lock chain and the bitmaps of the
  lock_t objects in it (lock_rec_bitmap_reset and the new bit set by
  lock_rec_add_to_queue()).
- It also protects lock->type_mode, including the LOCK_WAIT bit. The
  canonical clear in lock_reset_lock_and_trx_wait() runs under the cell
  latch, and lock_grant() invokes it before taking trx->mutex, so the bit
  is cell-latch state rather than trx->mutex state. Phase 1 only clears
  the bit and leaves trx->lock.wait_lock intact; the copy in old_locks
  keeps LOCK_WAIT and phase 2 re-adds the lock with it, so the wait
  relationship (guarded by lock_sys.wait_mutex) is preserved across the
  move. Neither trx->mutex nor wait_mutex is required here.
- Each owning trx's mutex is acquired per-iteration to protect that trx's
  trx_locks list and lock_heap during lock_rec_add_to_queue().

The global exclusive latch was over-strong: it blocked every concurrent
lock_sys.rd_lock() acquirer in lock_rec_lock() and lock_table()
server-wide for the duration of the reorganize, contributing
disproportionately to the lock_sys.latch convoy under heavy concurrency.

The TMLockGuard fast-path empty check at the top of the function is
preserved; for cells with no locks the cost is still just a TSX-elided
read.