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
Rex Johnston
s
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, 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.
DerZc
MDEV-40689 Wrong result: BIT_AND/BIT_OR/BIT_XOR in WINDOW functions over a frame containing NULL

BIT_AND, BIT_OR, and BIT_XOR window functions can return incorrect
values as a sliding frame moves past NULL input rows.

Adding a NULL argument leaves the bit-aggregate state unchanged, but
removing that row unconditionally calls remove_as_window() with
val_int()'s value. The removal path therefore changes state for a row
that never contributed to the aggregate.

Evaluate the departing window argument once and retain its unsigned
value. Call remove_as_window() only when the evaluated argument is
non-NULL. Leave the existing incremental window algorithm and non-window
aggregation path in place.

The regression checks all three bit aggregates over ROWS BETWEEN 1
PRECEDING AND CURRENT ROW with interleaved NULL and non-NULL values,
including removal of a real zero and restoration of the neutral values
after the frame becomes all-NULL.

Bug report: https://jira.mariadb.org/browse/MDEV-40689
Oleksandr Byelkin
MDEV-41186 Fix stack-buffer-overflow in make_unique_constraint_name

A multi-byte PERIOD name at the 64-character limit (192 bytes) filled
the name buffer exactly, leaving no room for the '_N' suffix appended
when generating a unique name for the implicit CHECK constraint.

Truncate on a character boundary, but only once a suffix is actually
needed (mirroring make_unique_key_name), so a non-colliding name is
never altered.

Co-Authored-By: Claude Sonnet 5 <[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.

The above change has exposed an issue with key length calculation
on MS Windows.  The field is a ulong and with all 32 key parts
wanted, we calculate this as (1UL << 32) - 1.  The first part of
the calculation overflows the field.  The result is undefined in C++.

Fix:  change key_part_map to 64 bits long, so it is the same on Linux
and MS Windows.
Sergei Golubchik
MDEV-39625 plugin/auth_pam/testing/CMakeLists.txt breaks INSTALL_MYSQLTESTDIR= suppression
Alessandro Vetere
MDEV-39792 InnoDB: ALTER TABLE FORCE triggers assertion "s" in buf_page_get_gen()

When rebuilding a table from ROW_FORMAT=COMPACT or DYNAMIC into
ROW_FORMAT=REDUNDANT, row_merge_buf_add() fetches the full value of an
externally stored (off-page) CHAR column in a multi-byte character set
and pads it to REDUNDANT's fixed local width via
row_merge_buf_redundant_convert(). That helper already dereferences the
BLOB and calls dfield_set_data(), which clears the field's "externally
stored" flag, since the value is now held in full locally.

The "flag externally stored fields" step further down in
row_merge_buf_add() did not know this had happened. It still consulted
the row_ext_t cache built from the original (pre-conversion) record and,
for a column that is not part of the clustered index's unique key,
called dfield_set_ext() again on the very field that had just been
converted, without restoring its data pointer to a valid 20-byte
external reference. row_merge_copy_blobs() would then read the tail of
the padded, space-filled buffer as if it were a BTR_EXTERN_FIELD_REF,
deriving a garbage tablespace id and crashing buf_page_get_gen()'s
fil_space_get() assertion when the alter tried to build the new
clustered index.

Skip the re-flagging step for a field whose "externally stored" flag is
no longer set. row_build() flags every off-page column, and the
row_ext_t cache only holds a subset of those columns, so a field that
is not flagged is either a converted one (already fully local) or one
that the cache does not hold.

With the field no longer re-flagged, the rebuild completes, and the
rebuilt table passes CHECK TABLE with the full column value.

The MDEV-31025 case in innodb.default_row_format_alter failed on
innodb_page_size=4k and 8k: its ROW_FORMAT=REDUNDANT table has eight
utf32 CHAR(255) columns, which CREATE TABLE rejects with
ER_TOO_BIG_ROWSIZE on those page sizes. Derive the number of columns
from the page size, so that the record still exceeds the maximum local
record size and the fixed-length column c is stored externally. The
whole test now passes on every page size.
Marko Mäkelä
Merge 13.1 into main
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.

The above change has exposed an issue with key length calculation
on MS Windows.  The field is a ulong and with all 32 key parts
wanted, we calculate this as (1UL << 32) - 1.  The first part of
the calculation overflows the field.  The result is undefined in C++.

Fix:  change key_part_map to 64 bits long, so it is the same on Linux
and MS Windows.
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.

The above change has exposed an issue with key length calculation
on MS Windows.  The field is a ulong and with all 32 key parts
wanted, we calculate this as (1UL << 32) - 1.  The first part of
the calculation overflows the field.  The result is undefined in C++.

Fix:  change key_part_map to 64 bits long, so it is the same on Linux
and MS Windows.
Thirunarayanan Balathandayuthapani
MDEV-28730 fixup: clang -Wunused-but-set-global
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.

The above change has exposed an issue with key length calculation
on MS Windows.  The field is a ulong and with all 32 key parts
wanted, we calculate this as (1UL << 32) - 1.  The first part of
the calculation overflows the field.  The result is undefined in C++.

Fix:  change key_part_map to 64 bits long, so it is the same on Linux
and MS Windows.
Sutou Kouhei
Fix auto directory creation for absolute mroonga_database_path_prefix (#1166)

mkdir_p() tried stat("") and mkdir("") for the leading directory
separator of an absolute path and gave up. So we couldn't create
database directory automatically for absolute
mroonga_database_path_prefix such as "/var/lib/mroonga/".

This also treats EEXIST from mkdir() as success because another process
may create the directory after our stat().

Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Marko Mäkelä
Fix a race between IMPORT TABLESPACE and BACKUP SERVER
mariadb-PranavTiwari
MDEV-39343- Added support of upgrade info system table and captured in mariadb dump tool.
Oleksandr Byelkin
MDEV-41258 Crash in Item_func_nextval on prepared re-execution

A table's DEFAULT NEXTVAL(seq) column keeps a per-open TABLE_LIST
describing the sequence table, allocated on that TABLE's own mem_root.
add_internal_tables() cached a matching prelocking entry across
statement re-executions by comparing db.str/table_name.str pointer
identity. If the owning table was closed and reopened between two
executions (FLUSH TABLE, or ordinary table-cache eviction under
concurrent load), those pointers went stale, and pointer-identity
matching also failed to recognize the reopened table's fresh entry as
the same one, leaving a dangling duplicate in the prelocking list that
still got opened and crashed.

Match entries by (owning TABLE_LIST, position in its internal_tables
list) instead, which survives a reopen. Deep-copy db/table_name onto
the statement's own arena once, at entry creation, instead of aliasing
TABLE-owned memory, so they never need refreshing.

Separately, the relink step was gated the same way as trigger/routine
prelocking discovery (has_prelocking_list), which stays true forever
once a statement's prelocking set includes a trigger -- silently
skipping the relink on every execution after the first for any such
statement. Moved it into its own function, called unconditionally per
table from open_and_process_table().

Also clear a stale internal-table entry's linked_table in
TABLE_LIST::reinit_before_use() when its owning table's own open gets
skipped in a given execution, so a later open_table() backlink write
can't land on memory the owner may have already freed.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Marko Mäkelä
MDEV-40852 Redundant checkpoint after innodb_log_archive startup

log_t::set_recovered(): Do not unnecessarily set the
circular_recovery_from_sequence_bit_0 flag for innodb_log_archive=ON
format files.

The purpose of the flag is to ensure that an extra checkpoint will be
written when converting the log to innodb_log_archive=OFF format. The
scenario that we want to prevent is that the log originally was in
innodb_log_archive=OFF format and had wrapped around an odd number of
times since the file creation, that is, the sequence bit at the end
of the mini-transactions since the latest checkpoint is 0. After a
conversion to innodb_log_archive=ON format, old records would carry
the sequence bit 0 and new ones the bit 1. This is fine, because the
recovery will ignore the sequence bit; innodb_log_archive=ON files
never wrap around. However, when the log is converted back to
innodb_log_archive=OFF format, we must guarantee that all sequence
bits since the latest checkpoint were written as 1.
Aleksey Midenkov
MDEV-41157 Follow-up test fix: strip version-dependent charset result

Follow-up to 6c391b92055.

SHOW CREATE DATABASE always appends "/*!40100 DEFAULT CHARACTER SET
... */", but the default charset differs by version (latin1 on 11.4,
utf8mb4 on 11.8+). Strip it instead of matching a specific value,
since it is not the subject for the fix.

Also switch to evalp: same execution, but logs "$var" instead of the
substituted value, so the replace_regex/disable_query_log hacks go away.
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.

The above change has exposed an issue with key length calculation
on MS Windows.  The field is a ulong and with all 32 key parts
wanted, we calculate this as (1UL << 32) - 1.  The first part of
the calculation overflows the field.  The result is undefined in C++.

Fix:  change key_part_map to 64 bits long, so it is the same on Linux
and MS Windows.
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.

The above change has exposed an issue with key length calculation
on MS Windows.  The field is a ulong and with all 32 key parts
wanted, we calculate this as (1UL << 32) - 1.  The first part of
the calculation overflows the field.  The result is undefined in C++.

Fix:  change key_part_map to 64 bits long, so it is the same on Linux
and MS Windows.
Vladislav Vaintroub
MDEV-41008: Fix X509 issuer/subject comparison for OpenSSL 3

OpenSSL 3 escapes '/' and '+' in X509_NAME_oneline() output; OpenSSL 1.1
and WolfSSL don't. A REQUIRE ISSUER/SUBJECT grant from one library can
stop matching after switching to another.

Default comparison stays strcmp(). old_mode=X509_LENIENT_COMPARE opts
into falling back to an escape-aware compare, applied to whichever side
the currently-linked library's own escaping affects, at the cost of
reopening the ambiguity a crafted certificate could exploit to
impersonate another identity.

Adds regression tests against a real certificate with an ambiguous CN

Assisted-by: Claude Sonnet 5 <[email protected]>
Daniel Bartholomew
bump the VERSION
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.

The above change has exposed an issue with key length calculation
on MS Windows.  The field is a ulong and with all 32 key parts
wanted, we calculate this as (1UL << 32) - 1.  The first part of
the calculation overflows the field.  The result is undefined in C++.

Fix:  change key_part_map to 64 bits long, so it is the same on Linux
and MS Windows.
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.

The above change has exposed an issue with key length calculation
on MS Windows.  The field is a ulong and with all 32 key parts
wanted, we calculate this as (1UL << 32) - 1.  The first part of
the calculation overflows the field.  The result is undefined in C++.

Fix:  change key_part_map to 64 bits long, so it is the same on Linux
and MS Windows.
Marko Mäkelä
fixup! 5d6b8a3178e12a53af30842560fcec22d51d9275
Vladislav Vaintroub
MDEV-41008: Fix X509 issuer/subject comparison for OpenSSL 3

OpenSSL 3 escapes '/' and '+' in X509_NAME_oneline() output; OpenSSL 1.1
and WolfSSL don't. A REQUIRE ISSUER/SUBJECT grant from one library can
stop matching after switching to another.

Default comparison stays strcmp(). old_mode=X509_LENIENT_COMPARE opts
into falling back to an escape-aware compare, applied to whichever side
the currently-linked library's own escaping affects, at the cost of
reopening the ambiguity a crafted certificate could exploit to
impersonate another identity.

Adds regression tests against a real certificate with an ambiguous CN

Assisted-by: Claude Sonnet 5 <[email protected]>
Vladislav Vaintroub
MDEV-41008: Fix X509 issuer/subject comparison for OpenSSL 3

OpenSSL 3 escapes '/' and '+' in X509_NAME_oneline() output; OpenSSL 1.1
and WolfSSL don't. A REQUIRE ISSUER/SUBJECT grant from one library can
stop matching after switching to another.

Default comparison stays strcmp(). old_mode=X509_LENIENT_COMPARE opts
into falling back to an escape-aware compare, applied to whichever side
the currently-linked library's own escaping affects, at the cost of
reopening the ambiguity a crafted certificate could exploit to
impersonate another identity.

Adds regression tests against a real certificate with an ambiguous CN

Assisted-by: Claude Sonnet 5 <[email protected]>
Alessandro Vetere
MDEV-39792 InnoDB: ALTER TABLE FORCE triggers assertion "s" in buf_page_get_gen()

When rebuilding a table into ROW_FORMAT=REDUNDANT, row_merge_buf_add()
fetches the full value of an externally stored (off-page) CHAR/VARCHAR
column and pads it to REDUNDANT's fixed local width via
row_merge_buf_redundant_convert(). That helper already dereferences the
BLOB and calls dfield_set_data(), which clears the field's "externally
stored" flag, since the value is now held in full locally.

The "flag externally stored fields" step further down in
row_merge_buf_add() did not know this had happened. It still consulted
the row_ext_t cache built from the original (pre-conversion) record and,
for a column that is not part of the clustered index's unique key,
called dfield_set_ext() again on the very field that had just been
converted, without restoring its data pointer to a valid 20-byte
external reference. row_merge_copy_blobs() would then read the tail of
the padded, space-filled buffer as if it were a BTR_EXTERN_FIELD_REF,
deriving a garbage tablespace id and crashing buf_page_get_gen()'s
fil_space_get() assertion when the alter tried to build the new
clustered index.

Skip the re-flagging step for a field whose "externally stored" flag is
no longer set. row_build() flags every off-page column, and the
row_ext_t cache only holds a subset of those columns, so a field that
is not flagged is either a converted one (already fully local) or one
that the cache does not hold.

With the field no longer re-flagged, the rebuild completes, and the
rebuilt table passes CHECK TABLE with the full column value.

The MDEV-31025 case in innodb.default_row_format_alter failed on
innodb_page_size=4k and 8k: its ROW_FORMAT=REDUNDANT table has eight
utf32 CHAR(255) columns, which CREATE TABLE rejects with
ER_TOO_BIG_ROWSIZE on those page sizes. Derive the number of columns
from the page size, so that the record still exceeds the maximum local
record size and the fixed-length column c is stored externally. The
whole test now passes on every page size.
Aleksey Midenkov
MDEV-41157 Follow-up test fix: strip version-dependent charset result

Follow-up to 6c391b92055.

SHOW CREATE DATABASE always appends "/*!40100 DEFAULT CHARACTER SET
... */", but the default charset differs by version (latin1 on 11.4,
utf8mb4 on 11.8+). Strip it instead of matching a specific value,
since it is not the subject for the fix.
Thirunarayanan Balathandayuthapani
MDEV-41207 Acquire metadata locks for recovered transaction

Problem:
=======
A transaction being rolled back during recovery holds LOCK_IX on the
table(not the metadata locks), and the rollback thread holds
a reference on it.

An online ALTER TABLE on that table falls back to acquiring LOCK_S,
which conflicts and fails. prepare_inplace_alter_table_dict()
asserted that the reference count is 1 before checking whether
the table lock was acquired, so the reference still held by the
rollback thread makes the assertion fail.

Solution:
========
recovery_mdl: New class that holds the metadata locks which
trx_resurrect_table_locks() acquires for recovered transactions,
together with the background connection that owns them.
One MDL_ticket is acquired per table and shared by every recovered
transaction that modified the table, with a reference count, so
that the lock is released once the last of those transactions has
been completed.

trx_sys_t::recovery: Pointer to recovery_mdl, wrapped in
std::atomic, next to rw_trx_hash, which trx_t::free() accesses
anyway. Null pointer means that no recovered transaction holds
metadata locks, which is the normal state once recovery is over.

trx_lists_init_at_db_start(): Create recovery_mdl and publish it in
trx_sys.recovery before any metadata lock can be acquired, and
delete it again if no recovered transaction acquired any.

recovery_mdl::release(): Drop the references of a transaction,
releasing each metadata lock whose last reference is dropped.
This is the only place that releases them, so that a transaction
which was rolled back by trx_rollback_recovered(false) will
not keep its locks until shutdown.

trx_t::free(): Release the metadata locks of a recovered
transaction, once it has been completed. A single relaxed load of
trx_sys.recovery is all that an ordinary transaction pays.

trx_recovery_release(): Re-read trx_sys.recovery while holding
trx_recovery_mutex, because the object may have been deleted after
trx_t::free() read the pointer.

trx_recovery_prune_low(): Delete trx_sys.recovery once no recovered
transaction holds metadata locks any longer, so that neither the
locks nor the connection will outlive the recovered transactions.
This is skipped when the caller has a current_thd, such as a user
connection that is completing a transaction which was recovered in
the XA PREPARED state, and during shutdown, because
destroy_background_thd() would clear the current_thd of the caller.

trx_recovery_shutdown(): Destroy trx_sys.recovery, releasing
anything that is left. It is invoked by innodb_shutdown() only,
after trx_sys.close() has freed any recovered transaction that was
left.

prepare_inplace_alter_table_dict(): Remove the acquisition of an
InnoDB table lock for online ADD INDEX when a recovered transaction
holds a lock on the table.
Vladislav Vaintroub
MDEV-41008: Fix X509 issuer/subject comparison for OpenSSL 3

OpenSSL 3 escapes '/' and '+' in X509_NAME_oneline() output; OpenSSL 1.1
and WolfSSL don't. A REQUIRE ISSUER/SUBJECT grant from one library can
stop matching after switching to another.

Default comparison stays strcmp(). old_mode=X509_LENIENT_COMPARE opts
into falling back to an escape-aware compare, applied to whichever side
the currently-linked library's own escaping affects, at the cost of
reopening the ambiguity a crafted certificate could exploit to
impersonate another identity.

Adds regression tests against a real certificate with an ambiguous CN

Assisted-by: Claude Sonnet 5 <[email protected]>
Yuchen Pei
MDEV-40479 [fixup] Better coverage, formatting, etc.
Sergei Golubchik
MDEV-41253 RPM %pre scriptlet unconditionally resets a pre-existing mysql user's home directory to /nonexistent

keep resetting to not writable, but use an existing path
Thirunarayanan Balathandayuthapani
MDEV-41207 Acquire metadata locks for recovered transaction

Problem:
=======
A transaction being rolled back during recovery holds LOCK_IX on the
table(not the metadata locks), and the rollback thread holds
a reference on it.

An online ALTER TABLE on that table falls back to acquiring LOCK_S,
which conflicts and fails. prepare_inplace_alter_table_dict()
asserted that the reference count is 1 before checking whether
the table lock was acquired, so the reference still held by the
rollback thread makes the assertion fail.

Solution:
========
recovery_mdl: New class that holds the metadata locks which
trx_resurrect_table_locks() acquires for recovered transactions,
together with the background connection that owns them.
One MDL_ticket is acquired per table and shared by every recovered
transaction that modified the table, with a reference count, so
that the lock is released once the last of those transactions has
been completed.

trx_sys_t::recovery: Pointer to recovery_mdl, wrapped in
std::atomic, next to rw_trx_hash, which trx_t::free() accesses
anyway. Null pointer means that no recovered transaction holds
metadata locks, which is the normal state once recovery is over.

trx_lists_init_at_db_start(): Create recovery_mdl and publish it in
trx_sys.recovery before any metadata lock can be acquired, and
delete it again if no recovered transaction acquired any.

recovery_mdl::release(): Drop the references of a transaction,
releasing each metadata lock whose last reference is dropped.
This is the only place that releases them, so that a transaction
which was rolled back by trx_rollback_recovered(false) will
not keep its locks until shutdown.

trx_t::free(): Release the metadata locks of a recovered
transaction, once it has been completed. A single relaxed load of
trx_sys.recovery is all that an ordinary transaction pays.

trx_recovery_release(): Re-read trx_sys.recovery while holding
trx_recovery_mutex, because the object may have been deleted after
trx_t::free() read the pointer.

trx_recovery_prune_low(): Delete trx_sys.recovery once no recovered
transaction holds metadata locks any longer, so that neither the
locks nor the connection will outlive the recovered transactions.
This is skipped when the caller has a current_thd, such as a user
connection that is completing a transaction which was recovered in
the XA PREPARED state, and during shutdown, because
destroy_background_thd() would clear the current_thd of the caller.

trx_recovery_shutdown(): Destroy trx_sys.recovery, releasing
anything that is left. It is invoked by innodb_shutdown() only,
after trx_sys.close() has freed any recovered transaction that was
left.

prepare_inplace_alter_table_dict(): Remove the acquisition of an
InnoDB table lock for online ADD INDEX when a recovered transaction
holds a lock on the table.
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.

The above change has exposed an issue with key length calculation
on MS Windows.  The field is a ulong and with all 32 key parts
wanted, we calculate this as (1UL << 32) - 1.  The first part of
the calculation overflows the field.  The result is undefined in C++.

Fix:  change key_part_map to 64 bits long, so it is the same on Linux
and MS Windows.
Dave Gosselin
MDEV-31180:  MyISAMMRG Crash on UPDATE of an updateable VIEW

Attach the children of a MERGE table once per statement, and keep the
value of pos_in_table_list for a MERGE table on subsequent executions
of a prepared statement.
Marko Mäkelä
fixup! b387a4a6f9f9b3194a29c1a80c39c983d5dc4fd5
Sergei Golubchik
workaround for https://bugzilla.redhat.com/show_bug.cgi?id=2390105
Sergei Golubchik
MDEV-39624 storage/connect/CMakeLists.txt: unguarded generator expression variable causes fatal error at cmake generate phase