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
Yuchen Pei
MDEV-25848 do not let get_mm_parts() match cloned key parts

get_claimed_key_part() appended clones at param->key_parts_end, so
every later get_mm_parts() call iterated over them too and cloned each
clone again. N independent predicates on the same RTREE/ARRAY field
thus produced 2^(N-1) key parts, exhausting MAX_KEY at the 8th
predicate (e.g. 8 ORed "x MEMBER OF (js)" lost range access).

Keep clones in a separate region after key_parts_end, tracked by
RANGE_OPT_PARAM::key_part_clones_end. get_mm_parts() only walks
key_parts..key_parts_end, so each predicate creates at most one clone
and N predicates use N key parts.

Assisted-By: Claude Opus 5.5 <[email protected]>
Rex Johnston
MDEV-41251 Wrong result with split materialized query

A query like

  SELECT * FROM t0 WHERE t0.b IN
    (SELECT t.n2 FROM t1, (SELECT n1, n2 FROM t1 GROUP BY n1, n2) t
      WHERE t.n1 = t1.n1 AND t1.c1 = 'a' UNION SELECT -1)

returned only the row of t0 that was read first, when the derived table t
was split-materialized.

The IN->EXISTS transformation wraps t0.b in an Item_cache owned by the
Item_in_optimizer, and injects t.n2 = <cache>(t0.b) into the subquery. The
optimizer then pushes an equality on n2 into the derived table, so that
the table only has to be filled with the matching rows.
TABLE::add_splitting_info_for_key_field() built the right side of that
equality as a deep copy of <cache>(t0.b). A copy of a cache is a second
cache: it read t0.b for the first row of t0 and kept that value, because
only the Item_in_optimizer stores new values, and it stores them into the
original cache. Every later refill of the derived table was filtered on
the first row's value.

The right side is an expression of the outer select used inside the select
that specifies the derived table. Add a copy hierarchy for that purpose.
Item::new_select_copy_with_checks(thd, item_select) returns a copy for use
in a select nested in item_select, the select the item belongs to. In the
nested select the copy is an outer reference to item_select:

- An Item_field is copied and its depended_from set to item_select. This is
  what add_splitting_info_for_key_field() did before with
  set_fields_as_dependent_processor, except that depended_from now names
  the select the column belongs to instead of the nested select.
- An Item_direct_view_ref, a column of a merged view or derived table, is
  also copied like a column: the copy refers to a new_select_copy() of the
  item the view column stands for. Copying it this way, as the deep copy
  did, keeps a column of a constant NULL-complemented table constant in the
  pushed equality (the MDEV-30081 test in main.derived_cond_pushdown still
  shows ref "const" for its LATERAL DERIVED table).
- Any other item that depends on tables of item_select is not copied. The
  copy is an Item_direct_ref to the original item, with depended_from set
  to item_select. So the nested select reads the cache, aggregate or
  subquery that its owner keeps up to date, instead of a copy of it that
  nobody refreshes. Item_default_value is treated this way too.
- An item that depends on no table of item_select is shared.

The copy is fixed, and only refers to tables outside the select it is used
in, which the wrapper asserts. add_splitting_info_for_key_field() now uses
it for the right side of the pushed equality, and no longer walks the copy
with set_fields_as_dependent_processor or calls update_used_tables() on
it. The debug-only copy of key_field->val used for the lookup still uses
deep_copy_with_checks(). The check_deep_copy() call on the right side is
removed, as it is no longer meant to be a deep copy.

A second test, taken from Dave Gosselin's MDEV-41251 commit, pushes a
comparison, dt.a <=> (t1.b = 1), and its row form. The deep copy of the
comparison was never fixed again. Its Arg_comparator still pointed at the
original, which sets null_value of the original, and a copied row
comparison had comparators set to NULL. The row of t1 with a NULL b was
missing from the result, and the row form crashed in
Arg_comparator::compare_row(). Now the comparison is not copied: the right
side refers to the original.

This commit was prepared with Claude Code (Opus 5), which designed and
wrote the new_select_copy() hierarchy, switched the split equality to it,
wrote the three-row test from the earlier rr analysis, added the
comparison test, confirmed in a build of the parent commit that both tests
fail without the change, and ran main and the SQL-layer suites in normal
and --ps-protocol mode.
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 the recovered
transaction have been completed.

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_resurrect_table_locks(): Acquire a shared metadata lock on each
table that the recovered transaction had modified, unless a lock on
the table was acquired for an earlier one, and reference it for this
transaction. Record every table in trx_t::mod_tables, so that
trx_t::commit_in_memory() will find it.

This includes transactions that were recovered in the XA PREPARED
state. They are completed by a user connection, which may issue
XA COMMIT or XA ROLLBACK at any time, or not at all before the next
shutdown. Until then, DDL must be blocked on the tables that they had
modified.

trx_resurrect_table_lock(): Resurrect one table lock and record the
table in trx_t::mod_tables.

trx_sys_t::recovery_release(): Release the metadata locks that were
acquired for a recovered transaction, and delete trx_sys.recovery if
this was the last recovered transaction that held any.
It is invoked by trx_t::commit_in_memory(), while trx_t::mod_tables
and trx_t::is_recovered are still valid. This is the only place that
releases the locks of a transaction, so that a transaction which was
rolled back by trx_rollback_recovered(false) will not keep its locks
until shutdown.

trx_sys_t::recovery_release_table(): Drop the reference that a
recovered transaction holds on the metadata lock of a table,
because its trx_t::mod_tables entry is being removed by
lock_release_on_rollback().

trx_sys_t::recovery_prune_low(): Detach 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. The caller will delete the object outside
recovery_mutex. 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_sys_t::recovery_shutdown(): Destroy trx_sys.recovery, releasing
anything that is left. It is invoked at the end of trx_sys_t::close()
only, after every transaction has been freed. No other thread can be
accessing trx_sys.recovery, and therefore recovery_mutex need not be
acquired.

trx_sys_t::recovery_thd(): Return the background connection, for the
rollback_wait debug injection in row_undo_mod().

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.
Otto Kekäläinen
Remove executable bit from files that are not executable

W: mariadb-server: executable-not-elf-or-script [usr/bin/wsrep_sst_common]
W: mariadb-test-data: executable-not-elf-or-script [usr/share/mariadb/mariadb-test/main/lowercase_table2.result]
W: mariadb-test-data: executable-not-elf-or-script [usr/share/mariadb/mariadb-test/suite/galera/t/MDEV-35511.test]
N:
N:  This executable file is not an ELF format binary, and does not start with
N:  the #! sequence that marks interpreted scripts. It might be a sh script
N:  that fails to name /bin/sh as its shell, or it may be incorrectly marked
N:  as executable. Sometimes upstream files developed on Windows are marked
N:  unnecessarily as executable on other systems.

Origin commits:
- 36eba988: lowercase_table2.result (already fixed once in 3812e1c9)
- 8fab1293: MDEV-35511.test

Additionally confirmed that there are no more test/result files with
executable bit in vain with:

    find mysql-test -executable -name *.test -or -executable -name *.result

The file usr/bin/wsrep_sst_common is a Bash "library" file that can't be
executed stand-alone. The proper long-term fix would be to move this to
a library directory out of the `/usr/bin` path.
bsrikanth-mariadb
MDEV-41749: FederatedX pushdown sends "<nop>(" in pushed-down SQL

A pushed-down statement containing "x < SOME (subquery)" failed on the
remote server with a syntax error, as the query text contained the
internal "<nop>(...)" wrapper. "x < ALL (subquery)" is wrapped in
"<not>(...)" in the same way.

Item_func_not_all::print() prints the wrapper whenever `show` is set.
Omit it when QT_PARSABLE is requested and print the wrapped predicate in
parentheses, as precedence() reports the wrapper, so a parent expression
would not add parentheses itself.

While the ALL/ANY subquery item is intact, args[0] prints the original
"x op ALL|ANY (subquery)". When the subquery is reduced to a constant
("x < ALL (SELECT 2)"), it is replaced by a comparison with the inverted
comparator, and the negation is held by "<not>". Print it explicitly as
"NOT (x >= 2)" for ALL, otherwise the remote server returns the
complementary rows. ANY/SOME needs no negation.

Item_allany_subselect::print() printed its left operand without
parentheses, so "(a XOR b) < ALL (subquery)" was pushed as
"a xor b < all (...)" and parsed by the remote server as
"a XOR (b < ALL ...)". Use print_parenthesised(), as
Item_in_subselect::print() does.

Add tests to federatedx_pushdown_upd_del covering SOME and ALL in
UPDATE, DELETE and SELECT, with results compared with pushdown OFF and
the pushed-down text checked in the remote general log.
Aleksey Midenkov
MDEV-40821 Wrong result after DELETE HISTORY or PORTION OF (10.11)

The parser assigned versioning conditions of DELETE HISTORY ... BEFORE
SYSTEM_TIME and period conditions of DELETE ... FOR PORTION OF to the
table pointed by last_table(). When the BEFORE SYSTEM_TIME or FOR
PORTION OF expression references another table (e.g. via a subquery or
a sequence function), last_table() is already switched to that table,
and the DELETE target gets no conditions.

DELETE HISTORY then deletes current rows permanently instead of
history, keeps the history it had to purge, and is checked for DELETE
privilege instead of DELETE HISTORY. DELETE HISTORY from a
non-versioned table is not rejected with ER_VERS_NOT_VERSIONED.
DELETE ... FOR PORTION OF deletes all rows of the table, ignoring the
period.

The fix assigns the conditions to the TABLE_LIST returned by
delete_single_table, i.e. the DELETE target itself, regardless of
tables added later in the statement.

DBUG_ASSERT in TABLE::vers_switch_partition() is removed. It checked
delete_history on last_table() and assumed no other table is opened
for write by DELETE HISTORY, which is false for the underlying table
of a view or a table locked by SELECT ... FOR UPDATE in the history
point. The DELETE HISTORY target is already skipped there by its own
delete_history check.
Vladislav Vaintroub
MDEV-41800 Flush stdout after mysqld --help

Under load on Windows, the last partial stdout buffer could be lost at
exit, so the --help output was truncated, and mysql-test-run.pl failed
to parse it. Flush explicitly.

Assisted-by: Claude:claude-sonnet-5-5
Rucha Deodhar
MDEV-41815: SIGSEGV in Item_trigger_row::cleanup on FLUSH TABLES after a
trigger runs DECLARE ROW TYPE OF cursor DEFAULT NEW
Rucha Deodhar
MDEV-41831: SET NEW = (SELECT ...) in a BEFORE INSERT trigger fails with
ER_OPERAND_COLUMNS (1241) on a single-column table
bsrikanth-mariadb
MDEV-41748: Syntax error with BETWEEN in FederatedX pushdown

A multi-table UPDATE/DELETE pushed down to FederatedX failed on the
remote server with a syntax error when the WHERE clause had a BETWEEN
whose bounds are constants, e.g.

  UPDATE t1 AS a, t1 AS b SET a.x=NULL WHERE a.x BETWEEN NULL AND NULL;

The bounds are wrapped in Item_cache objects. The cache was not filled
yet when the query was printed, so Item_cache::print() emitted
"<cache>(NULL)", which is not valid SQL.

Fix: when printing with QT_PARSABLE, an Item_cache that holds no value
now prints the item it caches. A cache that already holds a value still
prints it as a literal. Output for callers that do not pass
QT_PARSABLE is unchanged. Only FederatedX pushdown uses QT_PARSABLE.

Add a test that pushes down multi-table SELECT, UPDATE and DELETE with
NULL and DATE BETWEEN bounds, and checks both the statements the remote
server received and the resulting data.
Rucha Deodhar
MDEV-22675: Assertion `offset < table->s->reclength' failed in dump_leaf_key

Analysis:
The reclength depends on the size of each field of the temporary table plus
the null_bytes. Since null_bytes is 0 (because we’re in non-strict mode and
the source table fields can never be null), there is no need to keep track
of null values. Hence the total record length is just the sum of the sizes
of both fields. The second field will always have size 0 because its value
will always be an empty string. Hence it starts exactly where the first
field ends which equal to reclength. Hence the assertion failure.

Fix:
If pack_length() is 0 (which means the size of field is 0) so assigning the
result as empty string directly, the assertion is not valid in that case.
Thirunarayanan Balathandayuthapani
MDEV-41548 InnoDB: Cannot replay rename … because the target file exists

Problem:
=======
recv_rename_files() replayed the renames in tablespace id order,
because renamed_spaces was a std::map keyed by space id that kept
only the latest file name per tablespace. A multi-table RENAME
such as RENAME TABLE t2 TO t3, t1 TO t2 frees a file name for a
tablespace that may have a lower id, and replaying in id order
then fails with "Cannot replay rename of tablespace … because the
target file exists".

Solution:
========
renamed_spaces: Change to a std::vector of (id, from, to),
retaining every FILE_RENAME record in log order. The records are
appended only while recv_sys.file_checkpoint is set, hence exactly
once and in ascending LSN.

recv_rename_files(): Replay the records in that order, applying
one only when the tablespace currently uses the file name that the
record renames from. The order in which the server executed the
renames is always replayable, because each rename required its
target to be unoccupied.
Otto Kekäläinen
Fix most typos that `lintianspell` found

Before this change `lintianspell` reported:

    ± find * -type f | xargs spellintian
    BUILD/FINISH.sh: fi fi (duplicate word) -> fi
    BUILD/compile-pentium32-gcov: fi fi (duplicate word) -> fi
    BUILD/compile-dist: fi fi (duplicate word) -> fi
    BUILD/SETUP.sh: fi fi (duplicate word) -> fi
    BUILD/compile-solaris-sparc-purify: mysqld mysqld (duplicate word) -> mysqld
    BUILD-CMAKE: remebered -> remembered
    BUILD-CMAKE: "allows to" -> "allows one to"
    BUILD-CMAKE: "Let's you" -> "Lets you"
    client/mysqlbinlog.cc: they they (duplicate word) -> they
    client/mysqldump.c: query query (duplicate word) -> query
    client/mysqldump.c: name name (duplicate word) -> name
    client/mysqldump.c: flags flags (duplicate word) -> flags
    client/mysqldump.c: "allows to" -> "allows one to"
    client/mysqladmin.cc: wait wait (duplicate word) -> wait
    client/mysql_plugin.c: the the (duplicate word) -> the
    client/mysql.cc: comand -> command
    client/mysql.cc: mysql mysql (duplicate word) -> mysql
    client/mysql.cc: type type (duplicate word) -> type
    client/mysql.cc: prompt prompt (duplicate word) -> prompt
    client/mysql.cc: struct struct (duplicate word) -> struct
    client/mysqlslap.c: long long (duplicate word) -> long
    client/mysqlcheck.c: to to (duplicate word) -> to
    client/mysqltest.cc: long long (duplicate word) -> long
    client/mysqltest.cc: string string (duplicate word) -> string
    client/mysqltest.cc: the the (duplicate word) -> the
    client/mysqltest.cc: mysql mysql (duplicate word) -> mysql
    client/mysqltest.cc: flags flags (duplicate word) -> flags
    client/mysqltest.cc: query query (duplicate word) -> query
    client/mysqltest.cc: if if (duplicate word) -> if
    client/mysqltest.cc: not not (duplicate word) -> not
    cmake/ssl.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/mysql_version.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/aws_sdk.cmake: librairies -> libraries
    cmake/aws_sdk.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/submodules.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/install_macros.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/compile_flags.cmake: ENDFOREACH ENDFOREACH (duplicate word) -> ENDFOREACH
    cmake/dtrace.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/dtrace_prelink.cmake: ENDFOREACH ENDFOREACH (duplicate word) -> ENDFOREACH
    cmake/mariadb_connector_c.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/check_compiler_flag.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/zlib.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/versioninfo.rc.in: END END (duplicate word) -> END
    cmake/build_configurations/mysql_release.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/libutils.cmake: not not (duplicate word) -> not
    cmake/libutils.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/os/HP-UX.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/os/Windows.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/os/Windows.cmake: ENDFOREACH ENDFOREACH (duplicate word) -> ENDFOREACH
    cmake/os/Windows.cmake: "Allow to" -> "Allow one to"
    cmake/os/SunOS.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/numa.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/Internal/CPack/CPackRPM.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/readline.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/cpack_rpm.cmake: build build (duplicate word) -> build
    cmake/cpack_rpm.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/systemd.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/install_layout.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/plugin.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/for_clients.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/mysql_add_executable.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/make_dist.cmake.in: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/pcre.cmake: libary -> library
    cmake/pcre.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/create_initial_db.cmake: ENDFOREACH ENDFOREACH (duplicate word) -> ENDFOREACH
    cmake/cpu_info.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    cmake/package_name.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    CMakeLists.txt: hapen -> happen
    CMakeLists.txt: ENDIF ENDIF (duplicate word) -> ENDIF
    CMakeLists.txt: ENDFOREACH ENDFOREACH (duplicate word) -> ENDFOREACH
    configure.cmake: ENDIF ENDIF (duplicate word) -> ENDIF
    configure.cmake: funcion -> function
    dbug/dbug.c: frp frp (duplicate word) -> frp
    dbug/dbug.c: to to (duplicate word) -> to
    debian/salsa-ci.yml: mysql mysql (duplicate word) -> mysql
    debian/mariadb-server-10.6.preinst: fi fi (duplicate word) -> fi
    debian/mariadb-server-10.6.mariadb.init: fi fi (duplicate word) -> fi
    debian/po/ca.po: diferent -> different
    debian/mariadb-server-10.6.postinst: fi fi (duplicate word) -> fi
    debian/mariadb-server-10.6.templates: mysql mysql (duplicate word) -> mysql
    debian/mariadb-server-10.6.postrm: fi fi (duplicate word) -> fi
    debian/autobake-deb.sh: enviroment -> environment
    debian/additions/innotop/innotop.1: ae ae (duplicate word) -> ae
    debian/additions/innotop/innotop.1: Pages Pages (duplicate word) -> Pages
    debian/mariadb-common.postinst: fi fi (duplicate word) -> fi
    Docs/INSTALL-BINARY: mysql mysql (duplicate word) -> mysql
    extra/wolfssl/CMakeLists.txt: ENDIF ENDIF (duplicate word) -> ENDIF
    extra/wolfssl/CMakeLists.txt: endif endif (duplicate word) -> endif
    extra/perror.c: unknow -> unknown
    extra/innochecksum.cc: long long (duplicate word) -> long
    extra/innochecksum.cc: error error (duplicate word) -> error
    extra/innochecksum.cc: page page (duplicate word) -> page
    extra/innochecksum.cc: file file (duplicate word) -> file
    extra/mariabackup/backup_mysql.cc: long long (duplicate word) -> long
    extra/mariabackup/backup_copy.cc: "allows to" -> "allows one to"
    extra/mariabackup/xbcloud.cc: verison -> version
    extra/mariabackup/xbcloud.cc: recieved -> received
    extra/mariabackup/CMakeLists.txt: ENDIF ENDIF (duplicate word) -> ENDIF
    extra/mariabackup/xtrabackup.h: delimiters delimiters (duplicate word) -> delimiters
    extra/mariabackup/fil_cur.cc: tablepsaces -> tablespaces
    extra/mariabackup/fil_cur.h: tablepsaces -> tablespaces
    extra/mariabackup/xtrabackup.cc: neccessary -> necessary
    extra/mariabackup/xtrabackup.cc: delimiters delimiters (duplicate word) -> delimiters
    extra/mariabackup/xtrabackup.cc: loggin -> login
    extra/mariabackup/xtrabackup.cc: possiblity -> possibility
    extra/mariabackup/xtrabackup.cc: suffix suffix (duplicate word) -> suffix
    extra/mariabackup/wsrep.cc: long long (duplicate word) -> long
    extra/aws_sdk/CMakeLists.txt: "Allow to" -> "Allow one to"
    extra/replace.c: convinience -> convenience
    extra/readline/histlib.h: n n (duplicate word) -> n
    extra/readline/parens.c: delimiter delimiter (duplicate word) -> delimiter
    extra/readline/vi_mode.c: wc wc (duplicate word) -> wc
    extra/readline/display.c: e e (duplicate word) -> e
    extra/readline/display.c: v v (duplicate word) -> v
    extra/readline/display.c: postion -> position
    extra/readline/rldefs.h: n n (duplicate word) -> n
    extra/readline/history.c: carefull -> careful
    extra/readline/text.c: pased -> passed
    extra/readline/configure.in: dnl dnl (duplicate word) -> dnl
    extra/readline/configure.in: fi fi (duplicate word) -> fi
    extra/readline/readline.c: Initalize -> Initialize
    extra/readline/histexpand.c: upto -> up to
    extra/readline/histexpand.c: modfiers -> modifiers
    extra/CMakeLists.txt: ENDIF ENDIF (duplicate word) -> ENDIF
    include/mysql/plugin_audit.h.pp: long long (duplicate word) -> long
    include/mysql/service_encryption_scheme.h: long long (duplicate word) -> long
    include/mysql/plugin.h: long long (duplicate word) -> long
    include/mysql/plugin.h: prefix prefix (duplicate word) -> prefix
    include/mysql/psi/psi_base.h: "Allow to" -> "Allow one to"
    include/mysql/psi/psi.h: must must (duplicate word) -> must
    include/mysql/psi/psi.h: length length (duplicate word) -> length
    include/mysql/psi/psi.h: "Allow to" -> "Allow one to"
    include/mysql/service_progress_report.h: long long (duplicate word) -> long
    include/mysql/plugin_audit.h: long long (duplicate word) -> long
    include/mysql/plugin_auth.h.pp: long long (duplicate word) -> long
    include/mysql/auth_dialog_client.h: mysql mysql (duplicate word) -> mysql
    include/mysql/auth_dialog_client.h: type type (duplicate word) -> type
    include/mysql/auth_dialog_client.h: prompt prompt (duplicate word) -> prompt
    include/mysql/plugin_password_validation.h.pp: long long (duplicate word) -> long
    include/mysql/plugin_encryption.h.pp: long long (duplicate word) -> long
    include/mysql/plugin_data_type.h.pp: long long (duplicate word) -> long
    include/mysql/service_logger.h: long long (duplicate word) -> long
    include/mysql/client_plugin.h: type type (duplicate word) -> type
    include/mysql/client_plugin.h: value value (duplicate word) -> value
    include/mysql/service_wsrep.h: long long (duplicate word) -> long
    include/mysql/plugin_ftparser.h.pp: long long (duplicate word) -> long
    include/mysql/plugin_function.h.pp: long long (duplicate word) -> long
    include/my_global.h: long long (duplicate word) -> long
    include/json_lib.h: lenght -> length
    include/my_sys.h: long long (duplicate word) -> long
    include/mysql.h: long long (duplicate word) -> long
    include/myisam.h: dupplicated -> duplicated
    include/my_base.h: dupplicated -> duplicated
    include/big_endian.h: short short (duplicate word) -> short
    include/ma_dyncol.h: long long (duplicate word) -> long
    spellintian: can't decode ill-formed UTF-8 octet sequence <FF> in position 0 at /usr/share/perl5/Path/Tiny.pm line 2087.
    xargs: spellintian: exited with status 255; aborting

Fix all clear and easy to fix typos that have no functional effect,
and thus should be perfectly safe to do on the 10.6 branch.

This is intentionally done in a separate step from other typofixes for
easier patch management between upstream and downstream (Debian) MariaDB.
Oleksandr Byelkin
MDEV-41652 SIGFPE in get_next_time/Event_queue_element::compute_next_execution_time

get_next_time() took the interval value as int, so converting it to
seconds or months could overflow, e.g. 268435456 HOUR wrapped to 0
and the months branch divided by zero.

Pass the interval as longlong and reject month counts that do not
fit INTERVAL::month (32-bit on Windows).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Otto Kekäläinen
Document bashisms in scripts that are supposed to stay POSIX-compliant

Lintian reported bash-term-in-posix-shell for scripts that declare
/bin/sh as their interpreter:

    I: mariadb-client: bash-term-in-posix-shell '`echo "testing\c"' [usr/bin/mariadb-secure-installation:199]
    I: mariadb-server: bash-term-in-posix-shell '${BASH_VERSION' [usr/share/mariadb/wsrep_notify:86]
    I: mariadb-server: bash-term-in-posix-shell '[ "$url" ==' [usr/bin/mariadbd-safe:222]
    I: mariadb-server: bash-term-in-posix-shell 'let' [usr/bin/mariadbd-safe:41]
    I: mariadb-server: bash-term-in-posix-shell 'ulimit' [usr/bin/mariadbd-safe:718]
    I: mariadb-server: bash-term-in-posix-shell 'ulimit' [usr/bin/mariadbd-safe:838]
    I: mariadb-server-core: bash-term-in-posix-shell 'source tree,' [usr/bin/mariadb-install-db:100]

Only scripts/mysqld_safe.sh really uses non-POSIX shell features (local
variables and the == operator in test), but it should stay using sh
as mentioned in c10bed1.

The other reported scripts do run fine under /bin/sh and are only false
positives of the Lintian check:
- mariadb-secure-installation deliberately probes the shell's echo
  behaviour
- wsrep_notify intentionally checks for a Bash runtime and falls back
  to POSIX code when Bash is not available
- The `let` and `ulimit` hits in mariadbd-safe are respectively a word
  in a comment and a POSIX utility also provided by Dash
- `source tree,` is a word in a comment in mariadb-install-db

Also update the existing overrides to ensure paths and line numbers match.
Oleksandr Byelkin
MDEV-39306 fix race in versioning.rpl_row

The slave created table t before the master's previous DROP TABLE t
was replicated. Sync the slave after the drops.

Reviewed by [email protected]
Rex Johnston
MDEV-41228 Test deep clones of Item_cache items

We add Item::check_deep_copy(), which validates a clone against its original in
a debug build. It walks both item trees and reports, as notes, whether they
have the same shape with the same Item class at every node, and whether the
clone shares an Item object with the original. Sharing is what distinguishes
a shallow copy from a deep one: an item that is shallow by design, Item_field
for instance, still produces a separate object and only shares a Field, which
is not an Item.

Deep copies of Item_caches can be tested using mtr like this
mtr --mysqld=--debug-dbug=+d,item_cache_clones --suite=main --parallel=auto
or similar.

Another DBUG flag is "check_deep_copy".  This is used to check how many
items are deep cloned by producing a warning message.
Rucha Deodhar
MDEV-33843: Server crashes by stack-overflow with UPDATEXML

Analysis:
The stack size if insufficient and there is no stack overrun check.

Fix:
Add stack overrun check.
Rucha Deodhar
MDEV-41826: Crash in Table_triggers_list::mark_fields_used on INSERT after
trigger re-parse fails with unknown column
Daniel Black
Deb: latest Ubuntu named Tenacious T-Rex

Get the name into autobake in preparation for their release.

From: https://ubuntu.com/project/docs/release-team/list-of-releases/
Rucha Deodhar
MDEV-23500: Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())'
failed in Diagnostics_area::set_ok_status upon multi-table update

Analysis:
When NULL field from internal temporary table is copied to
NOT-NULL so there is error about truncation  but this error is not
reported so we get the failure.

Fix:
Return the error state.
nada
MDEV-37214 CREATE OR REPLACE USER must not drop the existing account on failure

CREATE OR REPLACE USER used to DROP the existing account before validating the new definition, so a failure after the DROP (e.g. an unknown auth plugin) permanently deleted the account without writing anything to the binlog, diverging master and replicas.

Validate and prepare the new account first; only wipe the account's privileges from the non-user grant tables once all checks pass, immediately before updating mysql.user/mysql.global_priv in place. A failure now leaves the existing account untouched.

  - CREATE OR REPLACE USER/ROLE now builds the replacement from a default row (as for a new account) instead of updating the old row field by field, so password, resource limits, SSL options and lock status do not survive the replace.
  - Orphan privileges (grant-table rows with no mysql.user row) are also removed.
  - Rebuild the role/user cross-reference arrays after a successful replace; without this, SHOW GRANTS could crash on an account that had been granted a role.
Oleksandr Byelkin
Fix use-after-poison on BINLOG with a Query event in EXECUTE IMMEDIATE

Query_log_event::do_apply_event() freed thd->mem_root, which inside a
BINLOG statement also freed the statement's own memory, e.g. Items of
EXECUTE IMMEDIATE freed later in THD::cleanup_after_query().

Free thd->mem_root only in replication/wsrep appliers, as
Rows_log_event::do_apply_event() does.

Reviewed by [email protected]
Rucha Deodhar
MDEV-36653: main.mysql_upgrade-28915 test case timeout

Analysis:
Concurrent execution of mysql_upgrade and the event scheduler causes a
metadata locking (MDL) deadlock between ALTER TABLE on system tables and
the initial loading/caching of the event table.

Fix:
Disable the event scheduler via 'SET GLOBAL event_scheduler=OFF' prior to
running the upgrade in the test case. This prevents concurrent conflicts
and allows the test to run reliably.
Rucha Deodhar
MDEV-23500: Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())'
failed in Diagnostics_area::set_ok_status upon multi-table update

Analysis:
When NULL field from internal temporary table is copied to
NOT-NULL so there is error about truncation  but this error is not
reported so we get the failure.

Fix:
Return the error state.
Jan Lindström
MDEV-40348 galera_var_reject_queries fails sporadically

Failure:
- wsrep_reject_queries=ALL_KILL signals node_1a's connection kill
  asynchronously (wsrep_close_client_connections(FALSE, ...)) and
  returns before the kill is processed.
- The test immediately queries node_1a, racing that signal. Most
  of the time the connection is already gone and the query gets a
  connection error, but under scheduler contention (seen on a busy
  CI worker) the query can still land on the live connection and
  get ER_UNKNOWN_COM_ERROR (1047), the same error plain
  wsrep_reject_queries=ALL already returns above, instead of a
  connection error.

Fix:
- Poll node_1a with SELECT * FROM t1 until it returns an actual
  connection error, tolerating 1047 as "not yet killed", the same
  technique include/wait_until_disconnected.inc already uses for
  this class of race.

Assisted-by: https://mariadb.org/governance/governance-ai-policy/
Yuchen Pei
MDEV-25848 do not let get_mm_parts() match cloned key parts

get_claimed_key_part() appended clones at param->key_parts_end, so
every later get_mm_parts() call iterated over them too and cloned each
clone again. N independent predicates on the same RTREE/ARRAY field
thus produced 2^(N-1) key parts, exhausting MAX_KEY at the 8th
predicate (e.g. 8 ORed "x MEMBER OF (js)" lost range access).

Keep clones in a separate region after key_parts_end, tracked by
RANGE_OPT_PARAM::key_part_clones_end. get_mm_parts() only walks
key_parts..key_parts_end, so each predicate creates at most one clone
and N predicates use N key parts.

Assisted-By: Claude Opus 5.5 <[email protected]>
Thirunarayanan Balathandayuthapani
MDEV-41360  OPTIMIZE TABLE crashes with ib_vector_size(optim->words) > 0 on FULLTEXT index with collation-equal words

Problem:
========
  OPTIMIZE TABLE on a FULLTEXT index crashes when the aux tables hold
two spellings of a word that are equal under the index collation.
The index lookup in fts_index_fetch_nodes() and the DELETE in
fts_optimize_write_word() both compare words by collation,
but fts_optimize_index_fetch_node() compares the bytes,
so each spelling becomes a separate fts_word_t.

fts_optimize_compact() then optimizes and writes back each of them
separately. Writing one deletes the rows of the other, including the
rows that were just written, so index entries can be lost. If all the
documents were deleted, the first write removes both words. The next
word that fts_optimize_words() reads from the zip buffer is the other
spelling, the fetch finds nothing, and the server aborts

Solution:
========
fts_optimize_collation_fetch_node(): New callback used only
by OPTIMIZE. It adds the fetched records whose words are
equal under the index collation to the same fts_word_t,
so the spellings are optimized and written back as one word.
The records arrive ordered by first_doc_id,
so the nodes stay in order.

fts_optimize_fetch_node(): The helper of the fetch callbacks,
which compares the words either by bytes or by the given collation.
fts_optimize_index_fetch_node() still compares by bytes, which is
what the information_schema code expects.

fts_optimize_words(): Use fts_optimize_collation_fetch_node().
The word read from the zip buffer can already
have been optimized together with an earlier spelling, so an empty
fetch is not an error. Skip the word instead of asserting.
Daniel Black
Merge branch '10.11' into MDEV-41800-flush
Rucha Deodhar
MDEV-22675: Assertion `offset < table->s->reclength' failed in dump_leaf_key

Analysis:
The reclength depends on the size of each field of the temporary table plus
the null_bytes. Since null_bytes is 0 (because we’re in non-strict mode and
the source table fields can never be null), there is no need to keep track
of null values. Hence the total record length is just the sum of the sizes
of both fields. The second field will always have size 0 because its value
will always be an empty string. Hence it starts exactly where the first
field ends which equal to reclength. Hence the assertion failure.

Fix:
If pack_length() is 0 (which means the size of field is 0) so assigning the
result as empty string directly, the assertion is not valid in that case.
Rucha Deodhar
MDEV-41827: SIGSEGV in Item_trigger_row::cleanup on condition pushdown of
row = NEW into derived table in trigger

Analysis:
During query cleanup, Query_arena::free_items() called delete_self() on
Item_trigger_row. Since trigger row items are allocated on a MEM_ROOT,
explicit heap deletion caused memory corruption and a segmentation fault.

Fix:
Override Item_trigger_row::delete_delf() to just return to prevent double
deletion.
Otto Kekäläinen
Add executable bit to files that are intended to be executable

Both files start with a #! interpreter line and are meant to be run as
programs. The files had originally correct executable bits, but
regressed in:
- 193ced9b: generate-ssl-certs.sh
- 8fab1293: normalize_query_id.pl

This fixes the following Lintian warnings:

    W: mariadb-test: script-not-executable [usr/share/mariadb/mariadb-test/lib/generate-ssl-certs.sh]
    W: mariadb-test-data: script-not-executable [usr/share/mariadb/mariadb-test/suite/plugins/t/normalize_query_id.pl]