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
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().
Yuchen Pei
MDEV-40486 Length check for vector fields in CREATE TABLE ... SELECT

The changes of MDEV-39558 2b6529426a7e7c65d286e093d84138be9dcc34a3
added length check assertion in Field_varstring constructors, and
length check in type inference for SELECT set operations, to emit
errors before reaching the assertions.

That change caused an error to turn into an assertion failure in a
separate path, when the length limit violation is not detected before
tripping the assertion. So in this patch we fix it by adding an
earlier length check in that path.

The reason that we place this check inside
Item_func_vec_fromtext::fix_length_and_dec rather than say
`create_field_for_create_select is for consistency:

If

create table t1 as select
vec_fromtext(concat('[',group_concat(1),']')) as c1 from seq_1_to_64;

fails due to length limit violation, then so should

create table t1 (v vector(64) not null);
insert into t1 select vec_fromtext(concat('[',group_concat(1),']'))
from seq_1_to_64;

Also use max_char_length() instead of max_length. This is a more
accurate length of characters. And add handling of empty string edge
case. Added testcases accordingly.

The change that uses max_char_length() causes side effects where
creating a table using a VEC_FROMTEXT(CHAR(1)) would result in a
0-dimensional vector field. This is accurate but 0-dim vector table
fields should not be allowed. So we add a check for that too, as well
as exceptions of NULL and (?) prepared statement placeholders.
Yuchen Pei
MDEV-40486 Length check for vector fields in CREATE TABLE ... SELECT

The changes of MDEV-39558 2b6529426a7e7c65d286e093d84138be9dcc34a3
added length check assertion in Field_varstring constructors, and
length check in type inference for SELECT set operations, to emit
errors before reaching the assertions.

That change caused an error to turn into an assertion failure in a
separate path, when the length limit violation is not detected before
tripping the assertion. So in this patch we fix it by adding an
earlier length check in that path.

Also use max_char_length() instead of max_length. This is a more
accurate length of characters. And add handling of empty string edge
case. Added testcases accordingly.
Rex Johnston
MDEV-39492 Parallel Query: choose the worker count for each scan

parallel_worker_threads was taken at face value: every scan asked for that many
workers, and execution read the session variable again rather than anything the
optimizer had decided. It is now the ceiling the user allows, and within it each
scan is given the count that costs least for that scan.

Another worker divides a scan a little further and adds a whole worker's setup,
measured at some 22 microseconds, so the two meet at a minimum. The cost is
convex in the count -- both divided terms fall, the setup term rises -- so
parallel_scan_worker_count() walks upwards until it stops falling, which is
short because the setup term is steep. A count whose cost is still worse than
reading the table serially is no count at all, and 0 says so, which is what
keeps a query too small to amortise a worker out of the workers without a
row-count threshold.

Per scan and not per query, because a query can hold more than one. TPC-H Q15
references its view twice and materialises it twice, and the two scans need not
be of the same table. With a ceiling of 64 a 25000-row table is given 14 workers
and a 200000-row one 39, and a query joining both shows [39, 14] against
["t_lge", "t_mid"] in the trace.

Execution now runs the count the plan was costed with. init_parallel_workers()
takes it from JOIN_TAB::parallel_workers, which make_join_readinfo() copies from
the chosen plan's POSITION, rather than reading the session variable a second
time. That closes three mismatches between what was costed and what ran:

  - A ceiling below PARALLEL_QUERY_MIN_WORKERS was costed as a parallel scan and
    named as chosen in the trace, and execution then declined it because the
    floor is applied there. With parallel_worker_threads=2 the trace claimed a
    parallel scan for a query that always ran serially.
  - A table InnoDB reports as one leaf page was costed as serial and then run in
    parallel from the session variable. main.parallel_query_worker_count
    asserted the first half of that and did not check the second.
  - The trace read JOIN::positions, the search's working array, where it should
    have read best_positions. Harmless while every candidate got the same count;
    not once they differ.

InnoDB's chunk ceiling needed one adjustment. pscan_chunk_count_estimate()
answers stat_n_leaf_pages, which is initialised to 1, only measured by ANALYZE,
and under-reports even then: a 2000-row table whose clustered index occupies six
pages records one leaf page, while a 40000-row one records 84 of its 97
correctly. So 1 means "a single page, or nothing measured", and using it as a
ceiling would refuse every small table its workers even though the engine goes
on to divide them into chunks enough for all of them -- t3 in
main.parallel_query_worker_count is one such table and gets three. Two or more
is worth believing; below that the real count at execution decides, as it did
before.

main.parallel_query_worker_count_per_scan covers the counts, the ceiling
binding, the ceiling below the floor, two scans in one query, and that the count
costed is the count run. Two existing tests changed:

  - main.parallel_query_excluded loaded three-row tables. Under a chosen count
    those are declined for being three rows, so every case in it would have read
    0 whether the gate excluded the table or not. The tables now hold 20000 rows
    so the exclusions are attributable to the gate. Its derived-table case also
    asserted that nothing was chosen while recording that something was; it now
    names the chosen tables, which shows the scan is of tb inside the derived
    table's own select and not of the derived table.
  - main.parallel_query_worker_count records 7 workers for t4 where it recorded
    8, that being the cost minimum below the ceiling, and t3's cost now changes
    with the count.

This commit was prepared with Claude Code: it wrote the per-scan choice and the
plumbing that carries it to execution, found by instrumenting the optimizer that
InnoDB's leaf-page statistic reads 1 for any small table and so could not serve
as the ceiling, and ran the SQL-layer suites under both protocols.
Sergei Golubchik
MDEV-40637 CONNECT crashes on double(255,50) in DOS table

cap the length correctly
forkfun
on rpm: don't set mysql user's $HOME to datadir

useradd set --home to %{mysqldatadir}, matching datadir.
Set --home to /nonexistent (as in deb)
forkfun
on rpm: don't set mysql user's $HOME to datadir

useradd set --home to %{mysqldatadir}, matching datadir.
Set --home to /nonexistent (as in deb)
Mohammad Tafzeel Shams
MDEV-39795: Assertion `n_reserved > 0' failed

Problem:
========

1. Assertion `n_reserved > 0` failed in fseg_create():

fsp_reserve_free_extents() has a special condition for small
tablespaces where it reserves individual pages instead of full
extents. In such cases, n_reserved can be 0 even when the
reservation succeeds, causing the assertion ut_ad(n_reserved > 0)
to fail incorrectly.

The code was checking n_reserved to determine whether a reservation
had already been attempted, but this logic breaks for small
tablespaces where pages, rather than extents, are reserved.

2. Encryption metadata not cleared for compressed-only pages:

buf_page_encrypt() only cleared encryption-related metadata
fields (key-version and crypt-checksum) when the page was
neither encrypted nor compressed. However, these fields should
also be cleared when page_compressed is true but encrypted is
false, to avoid leaving stale encryption metadata in
compressed-only pages.

Solution:
=========

buf_page_encrypt(): Refactored the early-return logic. Encryption
metadata fields are now cleared whenever encrypted is false,
regardless of page_compressed. The function returns early only
when both !encrypted and !page_compressed.

fseg_create(): Reintroduced a boolean variable `reserved` to track
whether fsp_reserve_free_extents() has been attempted (removed as
part of MDEV-38419 | c7313da), replacing assertion `n_reserved > 0`.
Added an early return when DB_DECRYPTION_FAILED is encountered
during inode allocation.

my_error_innodb(): Added handling for DB_DECRYPTION_FAILED to
report decryption errors to the user through ER_GET_ERRMSG.
Sergei Golubchik
MDEV-40637 CONNECT crashes on double(255,50) in DOS table

cap the length correctly
Sergei Petrunia
MDEV-39368: Add mtr --replay-server option to test Optimizer Context Replay

Re-commit the entire feature as one patch.

KEEP THIS AFTER ALL OPTIMIZER CONTEXT REPLAY COMMITS.
Sergei Golubchik
MDEV-40636 CSV crashes on DELETE

chain_size is the number of tina_set elements, not number of bytes

Assisted-By: Claude:claude-5-opus
Oleksandr Byelkin
Merge branch 'bb-11.4-release' into bb-11.8-release
Marko Mäkelä
squash! fd8ad0d39a674c65ef411ffcd8f867252012423b

buf_page_t::flush(): Refuse to write if the block is already write-fixed.

fil_space_t::backup_page_end(): Assert that buf_pool.mutex is being held.

fil_space_t::backup_end: Make Atomic_relaxed, so that it can be zeroed
while not holding buf_pool.mutex.

buf_page_t::write_fix_try(): Try to write-fix a block.

InnoDB_backup::backup_batch_start(): Write-fix all blocks that
reside in the range and are located in the buffer pool.

InnoDB_backup::backup_batch_stop(): Write-unfix all blocks.
Yuchen Pei
MDEV-40650 Fix main.partition_range_interval fails 32bit builders

Max timestamp is Y2106 only in 64bit
Vladislav Vaintroub
MDEV-33387 - multifactor authentication

Support "AND" between authentication plugins in CREATE/ALTER USER, so
that a user must pass every factor to log in (multi-factor auth), in
addition to the existing "OR" (alternative plugins). Mixing AND and OR
in one user definition is rejected.

  CREATE USER u IDENTIFIED VIA mysql_native_password AS PASSWORD('...')
                      AND some_other_plugin USING '...';

Grammar and storage
  - USER_AUTH gets a logical_operator (NONE/OR/AND) telling how each factor
    combines with the next; the parser tags the factor list and rejects a
    mix of AND/OR.
  - The operator is persisted in mysql.global_priv: the factor array is
    stored under "auth_and" (mirroring the existing "auth_or"). ALTER USER
    that collapses a multi-factor account back to a single plugin removes
    the stale "auth_and"/"auth_or" key.
  - SHOW CREATE USER prints " AND " between factors.
  - Two password-based (hashing) plugins in one AND chain are rejected;
    at most one factor may carry a password hash.

Authentication protocol
  - New client capability CLIENT_MULTI_FACTOR_AUTHENTICATION and an
    AuthNextFactor (0x02) command that tells the client to proceed to the
    next factor after the current one succeeded. send_plugin_request_packet
    becomes send_change_plugin_packet, handling both the auth-switch (0xFE)
    and next-factor (0x02) commands. Clients that do not announce the
    capability fall back to an auth switch.
  - acl_authenticate() runs the factors sequentially for AND (every factor
    must return CR_OK), while OR keeps its "first success wins" behavior.

TLS server-identity via password hash
  - When the connection uses a self-signed certificate and no CA is
    configured, the server sends a fingerprint challenge in the OK packet,
    computed from the certificate fingerprint and the password hash. For a
    multi-factor account the salt of the first password-hashing factor is
    used. The client recomputes it and, on a match, trusts the certificate
    even with --ssl-verify-server-cert, so password-based verification of
    the server does not raise a certificate error.

Tests
  - New plugins suite tests: mfa (portable machinery: AuthNextFactor round
    trip, non-hashing factor, auth_and persistence and ALTER round-trip,
    distinct per-factor secrets, negative cases, TLS fingerprint),
    mfa_unix (unix_socket + password), mfa_win (named_pipe/gssapi +
    password), mfa_unix_pam (password + PAM PIN).
  - auth_gssapi multiauth trimmed to the OR cases it still owns.

Client side changes are in the bundled libmariadb (submodule bump).

Assisted-By: Claude Opus 4.6 <[email protected]>
Vladislav Vaintroub
Support multi-factor authentication MySQL way

- Allow to specify password2/password3 via
mysql_optionsv(mysql,MYSQL_OPT_USER_PASSWORD, factor,N)

- Handle 0x2 (AuthNextFactor) server packet
Switch password according to factor

- make sure TLS "trust" works for self-signed certificate
if any of the MFA factors is password-based (e.g
gssapi + mysql_native_password would use second factor's
verification)
Yuchen Pei
MDEV-40650 Fix main.partition_range_interval fails 32bit builders

Max timestamp is Y2038 in 32bit, but Y2106 in 64bit
Raghunandan Bhat
MDEV-39169 Make the resolveip test honest about reverse lookups (testfix 2)

The test piped resolveip through sed patterns that rewrote its failure
message into the expected success line, and the pipe also discarded the
exit status - the test could not fail.  Removing the masking exposes
the real issue: reverse lookup results are OS dependent.  The name of
::1 differs per system, and ::ffff:127.0.0.1 has a name on glibc and
musl (which map it to 127.0.0.1) but none on macOS.

The suite.pm check bound a socket to the address, which asks the
kernel, not the resolver: it fails under net.ipv6.bindv6only=1 where
the lookup works and succeeds on macOS where it doesn't.  Revert it.

Instead, split the test in two:

- main/resolveip.test: deterministic cases, never skips.  Lookup
  failures are pinned with addresses that resolve nowhere (192.0.2.1,
  nonexistent.invalid), checking the exit status and that IPv4-mapped
  literals take the reverse-lookup path on every OS.

- main/resolveip_lookup.test: the reverse lookups.  A perl probe
  resolves the three loopback addresses with the same call resolveip
  makes, getnameinfo(NI_NAMEREQD), skips unless all have names, and
  returns the names so the test requires them exactly.

Output is normalized with replace_result/replace_regex instead of
pipes, keeping the exit status checked.

Co-Authored-By: Claude Fable 5 (1M context) <[email protected]>
bsrikanth-mariadb
MDEV-40383:innodb_gis.point_basic fails on replay

There are 2 problems: -
1. The REPLACE statement that is recorded doesn't store the
  value of geometry type field correctly.
2. The table definition that got recorded has fields with non-null constraint,
  and no default value is specified.
  Also, the "REPLACE INTO" statement that gets stored in the context,
  doesn't have any value specified for these non-null fields.

Solution is to: -
1. When using REPLACE INTO statement, store all the non-numeric values in HEX,
  whenever conversion from field's charset to output's charset is lossy.
2. Instead of storing only the column values that were projected in the
  query, store all the non-virtual column values into the recorded
  REPLACE INTO statement.

Implementation details: -
1. Introduce a new method is_charset_conversion_lossless() in filesort.cc,
  to check if the output charset to which field's data is being written to,
  results in a lossless conversion. If so, non-numeric values being witten
  using REPLACE INTO statement are stored in string representation,
  else they are converted to HEX.
2. From join_read_const(), and join_read_system() methods in sql_select.cc
  re-read the const row for all the non-virtual fields in the table.
  Similarly, for min/max optimization in opt_sum_query() of opt)_sum.cc,
  include all the non-virtual fields to be dumped into the "REPLACE INTO"
  statement.
  After the row is re-read and recorded, restore the table->read_set,
  table->status, and the const row, to the value that was before with
  the help of widen_read_set_no_vcols() method.
Fariha Shaikh
MDEV-40023 Error on unknown commands in check_expected_crash_and_restart

Anchor the wait/restart regexes in mariadb-test-run.pl and call
mtr_error() on anything else, so typos in expect files no longer fall
through to a default restart. Chomp $last_line before matching and skip
empty last lines to tolerate partial writes.

restart_bindir is kept; it is used during development to test upgrades
between two build trees.

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.
Sergei Golubchik
MDEV-40629 environment injection via wsrep bootstrap in the service file

* don't create mariadb-wsrep-new-cluster in the mariadbd-writable path,
  the server should not be able to poison the environment with OUTFILE.
  Create it in /run
* As in /run it must be deleted by root, let galera_new_cluster delete
  it, not the service
* wsrep-start-position cannot be created by root, so avoid a file
  for it at all

Assisted-By: Claude:claude-5-opus
Sergei Golubchik
MDEV-40636 CSV crashes on DELETE

chain_size is the number of tina_set elements, not number of bytes

Assisted-By: Claude:claude-5-opus
drrtuy
fix: MDEV-40610 fix for SQL injection in DEFAULT expression.
bsrikanth-mariadb
MDEV-40383:innodb_gis.point_basic fails on replay

There are 2 problems: -
1. The REPLACE statement that is recorded doesn't store the
  value of geometry type field correctly.
2. The table definition that got recorded has fields with non-null constraint,
  and no default value is specified.
  Also, the "REPLACE INTO" statement that gets stored in the context,
  doesn't have any value specified for these non-null fields.

Solution is to: -
1. When using REPLACE INTO statement, store all the non-numeric values in HEX,
  whenever conversion from field's charset to output's charset is lossy.
2. Instead of storing only the column values that were projected in the
  query, store all the non-virtual column values into the recorded
  REPLACE INTO statement.

Implementation details: -
1. Introduce a new method is_charset_conversion_lossless() in filesort.cc,
  to check if the output charset to which field's data is being written to,
  results in a lossless conversion. If so, non-numeric values being witten
  using REPLACE INTO statement are stored in string representation,
  else they are converted to HEX.
2. From join_read_const(), and join_read_system() methods in sql_select.cc
  re-read the const row for all the non-virtual fields in the table.
  Similarly, for min/max optimization in opt_sum_query() of opt)_sum.cc,
  include all the non-virtual fields to be dumped into the "REPLACE INTO"
  statement.
  After the row is re-read and recorded, restore the table->read_set,
  table->status, and the const row, to the value that was before with
  the help of widen_read_set_no_vcols() method.
Rex Johnston
MDEV-39492 Parallel Query: divide the scan's I/O cost by what is really read

scale_cost_for_parallel_scan() divided all three row components of a full scan
by the worker count. For the I/O component that is only true where a page has to
come from storage. A page the engine already holds in its cache is fetched from
memory, which the CPU and row-copy terms account for, so a scan of a table that
fits in the cache takes its parallelism from those two and gains nothing from
overlapping reads however many workers are asked for.

The I/O term now divides by the proportion of the table that cannot be resident:
the worker count for a table much larger than the engine's cache, 1.0 for one
that fits inside it, interpolating between. handler::engine_cache_size() is the
new accessor, answering 0 for an engine that has no cache or will not say, which
leaves such an engine costed exactly as before. ha_innobase returns
innodb_buffer_pool_size.

The ratio is taken from the configured cache size and the table's size on disk,
never from what the cache holds at the time, so costing the same query twice
gives the same answer and EXPLAIN does not move underneath the user.
DISK_READ_RATIO is a constant rather than a cache statistic for that same reason,
and optimizer_defaults.h says so.

Where the reads are real this term is what justifies a worker count far above
anything the CPU could use, which is the case worth costing correctly. Measured
on TPC-H SF1 Q6, LINEITEM at 1176 MB against a 128 MB buffer pool with
innodb_flush_method=O_DIRECT, on sixteen cores:

  workers  wall    CPU    cores busy  MB/s
  serial    1.30s  1.56s      1.2        885
  8        0.70s  2.27s      3.2      1621
  16        0.50s  2.16s      4.3      2194
  32        0.29s  1.90s      6.6      3576
  100      0.21s  1.91s      9.1      4210

The CPU the query consumes is flat across a 6.2x reduction in wall clock, so the
workers are not doing more work, they are waiting less: at one worker per core
only 4.3 cores' worth of work is in flight and the rest of the time the workers
are blocked in a read, holding no core. Adding md5() per row to the same scan
raises cores busy to 6.3 at sixteen workers and 13.0 at a hundred, and moves
where the curve flattens from the device's bandwidth to the core count -- the
same shape against a different ceiling, which is what this term describes.

The trace now reports parallel_scan_workers and parallel_scan_io_divisor beside
chosen_for_parallel_scan, so what the optimizer believed about the scan can be
read back. main.parallel_query_io_cost checks the divisor is exactly 1 for a
table inside the buffer pool, between 1 and the worker count for one several
times its size, and larger for more workers.

main.parallel_query_worker_count asserted that eight workers cost less than six
for t4. t4 is 1.3 MB against mtr's 8 MB pool, so its I/O term no longer divides
and the per-worker setup cost now outweighs what an eighth worker saves. The
assertion was there to show the ceiling is t4's leaf pages rather than the two
ranges its B-tree root starts with, which six workers against two shows just as
well without depending on where the setup cost crosses over.

This commit was prepared with Claude Code: it measured the worker-count curves
for Q6 and Q1 on the running server, including the CPU-time and throughput
columns that distinguish latency hiding from added parallelism, implemented the
term and the trace fields, and ran the SQL-layer suites under both protocols.
Yuchen Pei
MDEV-40486 Length check for vector fields in CREATE TABLE ... SELECT

The changes of MDEV-39558 2b6529426a7e7c65d286e093d84138be9dcc34a3
added length check assertion in Field_varstring constructors, and
length check in type inference for SELECT set operations, to emit
errors before reaching the assertions.

That change caused an error to turn into an assertion failure in a
separate path, when the length limit violation is not detected before
tripping the assertion. So in this patch we fix it by adding an
earlier length check in that path.

The reason that we place this check inside
Item_func_vec_fromtext::fix_length_and_dec rather than say
`create_field_for_create_select is for consistency:

If

create table t1 as select
vec_fromtext(concat('[',group_concat(1),']')) as c1 from seq_1_to_64;

fails due to length limit violation, then so should

create table t1 (v vector(64) not null);
insert into t1 select vec_fromtext(concat('[',group_concat(1),']'))
from seq_1_to_64;

Also use max_char_length() instead of max_length. This is a more
accurate length of characters. And add handling of empty string edge
case. Added testcases accordingly.

The change that uses max_char_length() causes side effects where
creating a table using a VEC_FROMTEXT(CHAR(1)) would result in a
0-dimensional vector field. This is accurate but 0-dim vector table
fields should not be allowed. So we add a check for that too, as well
as exceptions of NULL and (?) prepared statement placeholders.
bsrikanth-mariadb
MDEV-40383:innodb_gis.point_basic fails on replay

There are 2 problems: -
1. The REPLACE statement that is recorded doesn't store the
  value of geometry type field correctly.
2. The table definition that got recorded has fields with non-null constraint,
  and no default value is specified.
  Also, the "REPLACE INTO" statement that gets stored in the context,
  doesn't have any value specified for these non-null fields.

Solution is to: -
1. When using REPLACE INTO statement, store all the non-numeric values in HEX,
  whenever conversion from field's charset to output's charset is lossy.
2. Instead of storing only the column values that were projected in the
  query, store all the non-virtual column values into the recorded
  REPLACE INTO statement.

Implementation details: -
1. Introduce a new method is_charset_conversion_lossless() in filesort.cc,
  to check if the output charset to which field's data is being written to,
  results in a lossless conversion. If so, non-numeric values being witten
  using REPLACE INTO statement are stored in string representation,
  else they are converted to HEX.
2. From join_read_const(), and join_read_system() methods in sql_select.cc
  re-read the const row for all the non-virtual fields in the table.
  Similarly, for min/max optimization in opt_sum_query() of opt)_sum.cc,
  include all the non-virtual fields to be dumped into the "REPLACE INTO"
  statement.
  After the row is re-read and recorded, restore the table->read_set,
  table->status, and the const row, to the value that was before with
  the help of widen_read_set_no_vcols() method.
Yuchen Pei
MDEV-40486 Length check for vector fields in CREATE TABLE ... SELECT

The changes of MDEV-39558 2b6529426a7e7c65d286e093d84138be9dcc34a3
added length check assertion in Field_varstring constructors, and
length check in type inference for SELECT set operations, to emit
errors before reaching the assertions.

That change caused an error to turn into an assertion failure in a
separate path, when the length limit violation is not detected before
tripping the assertion. So in this patch we fix it by adding an
earlier length check in that path.

Also use max_char_length() instead of max_length. This is a more
accurate length of characters. And add handling of empty string edge
case. Added testcases accordingly.
Yuchen Pei
MDEV-40486 Length check for vector fields in CREATE TABLE ... SELECT

The changes of MDEV-39558 2b6529426a7e7c65d286e093d84138be9dcc34a3
added length check assertion in Field_varstring constructors, and
length check in type inference for SELECT set operations, to emit
errors before reaching the assertions.

That change caused an error to turn into an assertion failure in a
separate path, when the length limit violation is not detected before
tripping the assertion. So in this patch we fix it by adding an
earlier length check in that path.

Also use max_char_length() instead of max_length. This is a more
accurate length of characters. And add handling of empty string edge
case. Added testcases accordingly.
Sergei Golubchik
MDEV-40636 CSV crashes on DELETE

chain_size is the number of tina_set elements, not number of bytes

Assisted-By: Claude:claude-5-opus
forkfun
on rpm: don't set mysql user's $HOME to datadir

useradd set --home to %{mysqldatadir}, matching datadir.
Set --home to /nonexistent (as in deb)
Sergei Petrunia
MDEV-39368: Add mtr --replay-server option to test Optimizer Context Replay

Make --replay-server clean up the environment on replay server:
drop created tables, views, etc.
Sergei Golubchik
MDEV-40629 environment injection via wsrep bootstrap in the service file

* don't create mariadb-wsrep-new-cluster in the mariadbd-writable path,
  the server should not be able to poison the environment with OUTFILE.
  Create it in /run
* In /run it must be deleted by root, let galera_new_cluster delete it
  too, not the service
* wsrep-start-position cannot be created by root, so avoid a file
  for it at all

Assisted-By: Claude:claude-5-opus
Fariha Shaikh
MDEV-39459 Fix bad sync pattern for chain replication MTR tests

In chain replication (1->2->3), syncing only server_3 after
save_master_gtid on server_1 does not guarantee server_2 has committed,
because server_2's binlog dump thread can send events to server_3 before
commit_ordered() completes on server_2.

Fix affected rpl tests by syncing server_2 before server_3, and update
result files accordingly.

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.
forkfun
MDEV-40584 ST_CROSSES always returns 0 for different-dimension geometries

MDEV-36058 added a dimension-equality check ("Both geometries must
have the same number of dimensions") for SP_OVERLAPS_FUNC, but a
stray fall-through from SP_CROSSES_FUNC into that same case made
CROSSES share it too. CROSSES is defined precisely for geometries
of different dimensions, so any such pair now hit
"if (g1_dim != g2_dim) DBUG_RETURN(0)" and always returned 0.

Give SP_CROSSES_FUNC its own case again, calling
handle_sp_crosses_func_case() directly without the dimension check.
SP_OVERLAPS_FUNC keeps the check.
drrtuy
fix: MDEV-40386 disable MTR tests for MSAN builds b/c MSAN build is unstable.
forkfun
MDEV-40584 ST_CROSSES always returns 0 for different-dimension geometries

MDEV-36058 added a dimension-equality check ("Both geometries must
have the same number of dimensions") for SP_OVERLAPS_FUNC, but a
stray fall-through from SP_CROSSES_FUNC into that same case made
CROSSES share it too. CROSSES is defined precisely for geometries
of different dimensions, so any such pair now hit
"if (g1_dim != g2_dim) DBUG_RETURN(0)" and always returned 0.

Give SP_CROSSES_FUNC its own case again, calling
handle_sp_crosses_func_case() directly without the dimension check.
SP_OVERLAPS_FUNC keeps the check.