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
Thirunarayanan Balathandayuthapani
MDEV-41282 Recursion in InnoDB FTS AST causes stack-overflow (fts_ast_free_node/fts_ast_free_list)

Problem:
=======
fts_ast_free_node() and fts_ast_free_list() called each other, so
releasing the parse tree consumed one pair of thread stack frames
for every level of the tree.  sub_expr: '(' expr_lst ')' creates
one FTS_AST_SUBEXP_LIST per pair of parentheses, so a boolean
mode query with 2000 nested parentheses builds a chain of 4002
nodes, and fts_query_free() overflowed the thread stack
while freeing it.

fts_ast_visit() does not reach that depth, because
fts_ast_visit_sub_exp() limits the sub-expression nesting to
32 levels and returns DB_OUT_OF_MEMORY.
The parser has built the whole tree by then, and  it still has
to be freed.

fts_ast_node_print_recursive() recurses the same way. It is called
from fts_query_parse() when innodb_ft_enable_diag_print is enabled,
so it overflows the stack right after parsing, before the query is
executed.


Solution:
========
fts_ast_free_node(): Free the sub-tree with an explicit stack
instead of by recursion. The stack is threaded through the
next pointer of the very nodes that are about to be freed,
so it needs no extra memory and cannot fail to allocate.
A node is only pushed once it has been detached from the tree.
The children of a list are already chained to each other by next,
so a whole list is spliced onto the stack in one step.

fts_ast_free_list(): Removed, no longer needed.

fts_ast_node_print_recursive(): Stop at FTS_AST_PRINT_MAX_LEVEL and
print "..." instead of descending further.
Aleksey Midenkov
MDEV-40821 Wrong result after PORTION OF with subquery (11.4)

Single-table DELETE and UPDATE converted to multi-table (when a
subquery references the target table, or with UPDATE also another
table via semi-join) skipped FOR PORTION OF row splitting and the
constant expression check, so they deleted or updated whole rows
instead of the portion.

The fix prohibits processing DELETE ... FOR PORTION OF and UPDATE ...
FOR PORTION OF as multi-table, like DELETE ... RETURNING.
bsrikanth-mariadb
MDEV-41293: FederatedX: connection state after a net_read_timeout

Problem:
When reading the reply of the remote server times out, the client
library compiled into the server returns without closing the connection
and without setting a client error. FederatedX took the raw
ER_NET_READ_INTERRUPTED for an error of the remote server and went on
using a connection that still had the reply of the failed statement to
arrive. As a result:
* the next statement on that connection failed in various ways, either
  with ER_QUERY_ON_FOREIGN_DATA_SOURCE ("Server has gone away") or with
  an error packet that mysqltest took for a malformed packet;
* inside a transaction, the following statements continued on a new
  remote session in autocommit mode, so they were committed on the
  remote server one by one even though the local transaction was later
  rolled back. The savepoints of the lost session were also still
  remembered by FederatedX.
The same happened when the connection was lost while reading the reply.

Fix:
* After a timeout FederatedX closes the connection, so that the next
  statement opens a new one. The client still gets the error of the
  timeout, ER_NET_READ_INTERRUPTED.
* Whenever the connection is gone after a failed statement, timeout or
  not, the state of the lost session (autocommit mode, savepoints) is
  forgotten and the local transaction is marked to be rolled back, so a
  new connection starts the transaction again. This includes the case
  where the connection is lost while SET AUTOCOMMIT=0 is sent for the
  first statement of the transaction. The closed connection is also
  freed, which was leaked before.
* Errors of the client library are reported as
  ER_QUERY_ON_FOREIGN_DATA_SOURCE by ha_federatedx::info() as well, the
  same way as by the pushed down multi-table UPDATE/DELETE.
* The error state of ha_federatedx, read by info(), is initialized.
* A non-debug build checks the socket for EOF before it sends a command
  (net_clear()). If the remote server has already closed the connection, the
  write fails without the network layer raising an error, and the client
  would get ER_GET_ERRMSG ("Got error 10000 ...") intermittently. When the
  connection is lost and no error has been raised, raise
  ER_QUERY_ON_FOREIGN_DATA_SOURCE with the error of the client library. The
  COMMIT and ROLLBACK of the transaction still return their error to the
  caller.

Test: federatedx_pushdown_upd_del covers the timeout of a pushed down
multi-table UPDATE and DELETE and of reading a result, the statements
after it, the same inside a transaction, a connection killed in the
middle of a statement, a connection lost while SET AUTOCOMMIT=0 is sent
(also followed by a disconnect and a transaction in another session),
client library errors in info(), and that an error of the remote server
which merely has the code of ER_NET_READ_INTERRUPTED is not taken for a
timeout.
The two statements after the idle connection was killed accept
ER_NET_READ_ERROR (reported by the network layer in a debug build) or
ER_QUERY_ON_FOREIGN_DATA_SOURCE (non-debug build).
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.
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
Rex Johnston
MDEV-36295 backport followup, wrong version marker in test file
Marko Mäkelä
MDEV-41506: Broken recovery of SET GLOBAL innodb_log_archive=OFF on PMEM

recv_sys_t::find_checkpoint(): When modifying log_sys.archive,
remember to call mtr_t::finisher_update().

mtr_t::finisher_validate(): A validation predicate for srv_start().

Reviewed by: Thirunarayanan Balathandayuthapani
Vladislav Vaintroub
Fix main.grant_repair on Windows when user.MAI ends with Ctrl-Z

The test patches user.MAI from perl, opened in text mode. On Windows
that strips a trailing 0x1A byte on close, so the index file becomes
one byte shorter and the server reports a size mismatch instead of
repairing the table. Open the file with the :raw layer.

Assisted-by: Claude:claude-sonnet-5-5
Aleksey Midenkov
Fix SSL test failures with GnuTLS client (11.4)

With WITH_SSL=bundled the server uses wolfSSL and Connector/C is
built with GnuTLS. The GnuTLS backend reports a CA-signed server
certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN,
which neither --ssl-fp nor password-based verification can override
(OpenSSL reports it as MARIADB_TLS_VERIFY_TRUST).

The fix:

  main.ssl_fp      skip unless the client uses OpenSSL or LibreSSL
  main.mysql      pass --ssl-ca to a GnuTLS client for the
                  --ssl-verify-server-cert check
  rpl.rpl_semi_sync_no_missed_ack_after_add_slave
                  include default_client.cnf, so check-testcase
                  connects with --disable-ssl-verify-server-cert
                  (also done in 10.11)
Kristian Nielsen
After-merge fix of compilation failures

Signed-off-by: Kristian Nielsen <[email protected]>
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.
Vladislav Vaintroub
Fixup be807b2d047: match GnuTLS only, not every non-OpenSSL client

Schannel on Windows is not OpenSSL either, but handles these cases.

Assisted-by: Claude:claude-sonnet-5-5
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.
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.
Aleksey Midenkov
Merge 10.11 into 11.4
Thirunarayanan Balathandayuthapani
MDEV-41281 Unbounded Recursion in InnoDB FTS Boolean-Mode causes Stack-Overflow fts_ast_visit

expr_lst: expr_lst sub_expr wrapped the expression list parsed so
far in a newly created FTS_AST_LIST for every sub-expression,
so a query such as '(word)' repeated N times built N nested lists.
fts_ast_visit() recurses once per FTS_AST_LIST and overflowed the
thread stack; the default thread_stack was exhausted at about
2300 repetitions.

Append the sub-expression to the list that is already being built,
and create a list only when there is none yet, the way
the neighbouring expr_lst: expr_lst expr rule has always done.
The sub-expressions now become siblings of a single list and
the depth no longer grows.

This also corrects '+term (subexpr)'. The FTS_EXIST pass used to
run to completion in the inner list before the sub-expression was
unioned at the outer level, so rows that matched only the
sub-expression were returned.

Based on mysql/mysql-server@e46e9db484a051db6ffb0abd2b06d3b38ef71a35
bsrikanth-mariadb
MDEV-41293: FederatedX: connection state after a net_read_timeout

Problem:
When reading the reply of the remote server times out, the client
library compiled into the server returns without closing the connection
and without setting a client error. FederatedX took the raw
ER_NET_READ_INTERRUPTED for an error of the remote server and went on
using a connection that still had the reply of the failed statement to
arrive. As a result:
* the next statement on that connection failed in various ways, either
  with ER_QUERY_ON_FOREIGN_DATA_SOURCE ("Server has gone away") or with
  an error packet that mysqltest took for a malformed packet;
* inside a transaction, the following statements continued on a new
  remote session in autocommit mode, so they were committed on the
  remote server one by one even though the local transaction was later
  rolled back. The savepoints of the lost session were also still
  remembered by FederatedX.
The same happened when the connection was lost while reading the reply.

Fix:
* After a timeout FederatedX closes the connection, so that the next
  statement opens a new one. The client still gets the error of the
  timeout, ER_NET_READ_INTERRUPTED.
* Whenever the connection is gone after a failed statement, timeout or
  not, the state of the lost session (autocommit mode, savepoints) is
  forgotten and the local transaction is marked to be rolled back, so a
  new connection starts the transaction again. This includes the case
  where the connection is lost while SET AUTOCOMMIT=0 is sent for the
  first statement of the transaction. The closed connection is also
  freed, which was leaked before.
* Errors of the client library are reported as
  ER_QUERY_ON_FOREIGN_DATA_SOURCE by ha_federatedx::info() as well, the
  same way as by the pushed down multi-table UPDATE/DELETE.
* The error state of ha_federatedx, read by info(), is initialized.

Test: federatedx_pushdown_upd_del covers the timeout of a pushed down
multi-table UPDATE and DELETE and of reading a result, the statements
after it, the same inside a transaction, a connection killed in the
middle of a statement, a connection lost while SET AUTOCOMMIT=0 is sent
(also followed by a disconnect and a transaction in another session),
client library errors in info(), and that an error of the remote server
which merely has the code of ER_NET_READ_INTERRUPTED is not taken for a
timeout.
Thirunarayanan Balathandayuthapani
MDEV-41856 Forged column length during IMPORT TABLESPACE causes heap overflow on SELECT

Problem:
========
row_sel_field_store_in_mysql_format_func() trusted the field length
decoded from an InnoDB record and memcpy()'d that many bytes into
the fixed-size MySQL row buffer.

If a record's on-page variable-length-column length prefix is
corrupted, InnoDB copies the forged length's
worth of bytes into the row buffer, overflowing it. This is
reachable via a plain SELECT.

Fix:
====
row_sel_field_store_in_mysql_format_func(): for DATA_VARCHAR,
DATA_VARMYSQL, DATA_BINARY and DATA_MYSQL, clamp the field length to
the destination column's actual capacity before copying,
instead of trusting the record unconditionally. This turns a
corrupted length into a harmless truncation rather than a buffer
overflow.
Val Doroshchuk
MDEV-41372 Grant_tables::open_and_lock() leaves tables with a dangling pos_in_table_list

Grant_tables::open_and_lock() allocated the TABLE_LIST array with
my_malloc() and freed it before returning. The opened privilege
tables stay on thd->open_tables until close_mysql_tables() or the
end of the statement, and their TABLE::pos_in_table_list still
pointed into the freed array.

Allocate the array on thd->mem_root instead, so it lives as long
as the statement. It still stays off the stack, so the MDEV-34388
fix holds.
bsrikanth-mariadb
MDEV-41293: FederatedX: connection state after a net_read_timeout

Problem:
When reading the reply of the remote server times out, the client
library compiled into the server returns without closing the connection
and without setting a client error. FederatedX took the raw
ER_NET_READ_INTERRUPTED for an error of the remote server and went on
using a connection that still had the reply of the failed statement to
arrive. As a result:
* the next statement on that connection failed in various ways, either
  with ER_QUERY_ON_FOREIGN_DATA_SOURCE ("Server has gone away") or with
  an error packet that mysqltest took for a malformed packet;
* inside a transaction, the following statements continued on a new
  remote session in autocommit mode, so they were committed on the
  remote server one by one even though the local transaction was later
  rolled back. The savepoints of the lost session were also still
  remembered by FederatedX.
The same happened when the connection was lost while reading the reply.

Fix:
* After a timeout FederatedX closes the connection, so that the next
  statement opens a new one. The client still gets the error of the
  timeout, ER_NET_READ_INTERRUPTED.
* Whenever the connection is gone after a failed statement, timeout or
  not, the state of the lost session (autocommit mode, savepoints) is
  forgotten and the local transaction is marked to be rolled back, so a
  new connection starts the transaction again. This includes the case
  where the connection is lost while SET AUTOCOMMIT=0 is sent for the
  first statement of the transaction. The closed connection is also
  freed, which was leaked before.
* Errors of the client library are reported as
  ER_QUERY_ON_FOREIGN_DATA_SOURCE by ha_federatedx::info() as well, the
  same way as by the pushed down multi-table UPDATE/DELETE.
* The error state of ha_federatedx, read by info(), is initialized.

Test: federatedx_pushdown_upd_del covers the timeout of a pushed down
multi-table UPDATE and DELETE and of reading a result, the statements
after it, the same inside a transaction, a connection killed in the
middle of a statement, a connection lost while SET AUTOCOMMIT=0 is sent
(also followed by a disconnect and a transaction in another session),
client library errors in info(), and that an error of the remote server
which merely has the code of ER_NET_READ_INTERRUPTED is not taken for a
timeout.
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.
Sergei Golubchik
userstat: stack overflow on DROP TABLE with many index statistics

del_global_index_stats_for_table() collected all matching entries
into an array of MAX_INDEXES elements. Statistics of renamed indexes
stay in global_index_stats under their old names, so a table can have
more entries than that and DROP TABLE wrote past the array.

Delete the entries in batches of MAX_INDEXES.

Assisted-by: Claude:claude-opus-5-5
Yuchen Pei
MDEV-41805 Fix an infinite loop in iterated partition index scan

MDEV-37330 496aecf9251e3d74b83285f4e787daa9d8c37ae4 changed a for loop
in ha_partition::handle_unordered_scan_next_partition to a while loop,
with the loop index i advanced at the end of the loop body. This
causes an existing continue to skip the advancement, resulting in an
infinite loop. Fix this by restoring the while loop to a for loop.
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.
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-41814: Assertion `argp[arg_no]->fixed()' failed in
sp_head::execute_function

Analysis:
Passing OLD or NEW trigger rows as function arguments caused an assertion
failure (arg->fixed()) because Item_trigger_row::fix_fields() could return
early. This left the trigger row item in an unfixed state without setting
the item_base_t::FIXED flag.

Fix:
Restructured fix_fields() to return result and set the base_flags as needed.
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/
Sergei Golubchik
Wrong table name in the warning about missing statistical table

open_stat_table_for_ddl() printed the global stat_table_name, always
`table_stats`, instead of the name of the table it failed to open.

Assisted-by: Claude:claude-opus-5-5
Thirunarayanan Balathandayuthapani
MDEV-41665 InnoDB assertion with result != FTS_INVALID on DELETE IGNORE with FK cascades on tables with FULLTEXT indexes

Problem:
=======
A foreign key cascade records its FTS operations
(FTS_DELETE, FTS_INSERT) with fts_trx_add_op() while the
cascade is still being processed, before it is known whether
the row operation succeeds. If the row operation then fails
with an error that the statement survives, row_mysql_handle_errors()
rolls back the data to the row savepoint. The FTS state is not
rolled back, because fts_savepoint_rollback_last_stmt() is only
called when the whole statement is rolled back.

The stale FTS operations stay in trx->fts_trx. When the next row
cascades into the same child row, the same operation is recorded
again and fts_trx_row_get_new_state() hits an invalid transition
(FTS_DELETE -> FTS_DELETE), which crashes the server.

Solution:
========
Defer the FTS operations of a cascade until the row operation
has succeeded.

fts_trx_defer_op(): Queues the statement fts operation
in fts_trx_t::pending, and row_update_for_mysql_using_upd_graph()
applies them with fts_trx_flush_pending() after row_upd_step()
succeeds, before the row's own FTS operations.
The queue is discarded at the flushing operation and
in error handling part.
Rex Johnston
MDEV-36295 backport followup, wrong version marker in test file
Yuchen Pei
MDEV-41805 Fix an infinite loop in iterated partition index scan

MDEV-37330 496aecf9251e3d74b83285f4e787daa9d8c37ae4 changed a for loop
in ha_partition::handle_unordered_scan_next_partition to a while loop,
with the loop index i advanced at the end of the loop body. This
causes an existing continue to skip the advancement, resulting in an
infinite loop. Fix this by advancing i before the continue
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. A constant view column keeps its constant
  underlying item, which 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). If the copy still depends on a table of item_select, which happens
  for a constant column of a view on the NULL-complemented side of an outer
  join, since used_tables() then names that table, the copy gets its
  depended_from set as well.
- 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, Item_insert_value and
  Item_trigger_field are treated this way too, as they are not plain
  columns.
- An item that depends on no table of item_select is shared. This includes
  items whose deep_copy() returns nullptr, such as stored routine
  variables, which therefore no longer prevent splitting.

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.

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.

A third test pushes dt.a <=> v.one where v is a merged view with the
constant column one, on the NULL-complemented side of an outer join. It
covers the view column copy that depends on a table only through its
NULL-complemented table.

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. Claude Code (Fable 5.1) then reviewed the commit,
found and reproduced the NULL-complemented view column case, wrote its fix
and test, and reran the derived and SQL-layer tests.
Rex Johnston
MDEV-41632 UPPER(key_col) IN (constant subquery) does not use the index

Item_func_in::varchar_upper_cmp_transformer() rewrites
UPPER(key_col) IN (const, ...) into key_col IN (const, ...).

It needs a copy of the IN predicate to put the new first argument into,
it used deep_copy_with_checks(). A deep copy copies every node of the tree and
refuses as a whole if any node cannot be copied, so an IN list holding an
uncorrelated scalar subquery, which is constant but has no copy, silently
lost the rewrite: UPPER(a) IN ((SELECT MAX(c) FROM t2),'A-2') read the whole
table instead of using a range on the index on a. The rows returned were
correct; the symptom is the plan. After copying, the rewrite walked the copy
with cleanup_excluding_const_fields_processor and re-fixed it, which would
also have cleaned up a subquery had one been copied.

A copy for use in the same SELECT_LEX does not need to copy what can be
shared there. We add a separate copy hierarchy for that purpose.

Item::same_select_copy_with_checks() calls the protected virtual
Item::same_select_copy(), and cleans up every node it actually copied, so
that the caller only has to call fix_fields() on the result. fix_fields()
re-fixes the copied nodes and skips the shared ones, which are still fixed.
It does not use deep_copy() at any level; the only other copy function it
calls is shallow_copy() on the node being copied. It returns nullptr on out
of memory, and when a copied node's shallow_copy() returns nullptr; every
Item_func subclass whose shallow_copy() returns nullptr therefore overrides
same_select_copy() to share the item, and a future class in that position
must do the same or callers silently lose their rewrite.

Item default is to share the item.

Item_func, Item_cond and Item_row copy their node and recurse into their
arguments.

Item_func copies an argument that occurs more than once in args[] only once.
Item_bool_rowready_func2, Item_func_case_simple and Item_func_in detach the
comparators and value array they would otherwise share with the original,
as their deep_copy() overrides do. Item_func_interval points its row member
at the copied args[0], which it aliases.

Fields, references, constants, parameters, caches, subqueries, aggregate and
window functions are shared because they don't derive from Item_func.

Some Item_func subclasses cannot safely be copied, so they override
same_select_copy() to share the original instead:

- Functions that own memory or handles, which the copy would free a
  second time in cleanup() or its destructor: the regex functions, UDFs,
  stored functions, the JSON functions that build hashes, VEC_FromText,
  and the geometry functions with Gcalc state.
- Functions that their SELECT_LEX keeps a pointer to, so a copy would not
  be the item the SELECT_LEX uses: MATCH, ROWNUM and Item_equal.
- Functions whose copy would behave differently: RAND would restart its
  random sequence, and SET @var would assign the variable twice.
- TO_NUMBER, which refuses to be copied at all.
- Functions whose arguments point at each other: NULLIF uses args[0] a
  second time as args[2] and hides it from arg_count until cleanup(), and
  Item_in_optimizer's cache belongs to its subquery.

The rewrite now uses same_select_copy_with_checks() and no longer walks the
copy with a cleanup processor.

TABLE::add_splitting_info_for_key_field() uses it too, for the left side of
the equality it pushes into a split-materialized derived table: the item of
the derived table's select list, used in the WHERE condition of the same
select. Its real item is always a column, so the copy is the select list
item itself, where the deep copy made a second Item_field for it. Sharing
one item between the select list and the WHERE clause of a select is
intended here: state that condition processing sets on the item, such as
Item_field::item_equal, describes the same column in the same select. The
equality is fixed when it is injected.

This commit was prepared with Claude Code (Opus 5), which found the
subquery case that lost the rewrite and confirmed that the new test fails
without the change, designed and wrote the same_select_copy() hierarchy
and the list of shared Item_func classes, switched the casefold rewrite to
it, and ran main and the SQL-layer suites in normal and --ps-protocol mode.
Claude Code (Fable 5.1) then reviewed the commit, corrected the commit
message, kept Item_func_case_simple::shallow_copy() protected, added the
Item_func_interval override and the nullptr note, and re-ran the tests.
Sergei Golubchik
userstat: DROP TABLE and DROP INDEX leave stale usage statistics

delete_statistics_for_table() and delete_statistics_for_index()
removed the userstat entries only after opening the statistical
tables, and returned early when that failed.

Delete the userstat entries before opening the statistical tables.

Assisted-by: Claude:claude-opus-5-5
Rex Johnston
MDEV-36295 backport followup, wrong version marker in test file
Oleksandr Byelkin
MDEV-35867 mariadb-check --repair does not repair sequences, only changes the status to OK

REPAIR of a sequence table with more or fewer than one row reported OK.
Now ha_sequence::repair() checks the row count after the engine repair
and reports the sequence as corrupt.

Also a failed table recreate in REPAIR was reported as
"Table is already up to date" (bool result taken as HA_ADMIN_ALREADY_DONE).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
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]