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
Khaled Riyad
MDEV-41150 mariadb client: Ctrl-C does not interrupt tab separated result output

Ctrl-C sets interrupted_query and sends KILL QUERY to the server, but the
result is already fetched into the client by then, so killing the query
cannot stop the output. Only the printing loop can, by checking
interrupted_query.

print_table_data(), print_table_data_html(), print_table_data_xml() and
print_table_data_vertically() check it, print_tab_data() did not, so the
output of -s, -N and -B could not be interrupted.

Add the same check to print_tab_data().

No test case: the suite drives the client through a pty with socat, where
0x03 is not turned into a signal, and there is no other way in the suite to
signal a client while it is printing.
PranavKTiwari
MDEV-40167: GTT created with the InnoDB incorrectly accept FULLTEXT/VECTOR indexes
Problem:
GLOBAL TEMPORARY tables were not subject to the same option/index restrictions as session TEMPORARY tables. Several InnoDB and server-layer checks tested only tmp_table(), so GLOBAL TEMPORARY tables could bypass validation for VECTOR/FULLTEXT indexes, DATA DIRECTORY, KEY_BLOCK_SIZE, and ROW_FORMAT=COMPRESSED.

Cause:
global_tmp_table() was added as a separate predicate from tmp_table(), but not all temp-table checks were updated to test both, so GLOBAL TEMPORARY tables fell through to "permanent table" logic in several places.

Fix:
Added global_tmp_table() alongside tmp_table() at each affected check:

Reject VECTOR and FULLTEXT indexes on GLOBAL TEMPORARY tables.
Reject/warn on DATA DIRECTORY, KEY_BLOCK_SIZE, and ROW_FORMAT=COMPRESSED for GLOBAL TEMPORARY tables, with accurate wording in the DATA DIRECTORY warning.
Fixed zip_allowed and related ut_ad assertions to exclude GLOBAL TEMPORARY tables.
Fixed m_use_file_per_table in set_tablespace_type() to exclude GLOBAL TEMPORARY tables (also fixes m_use_data_dir).
GLOBAL TEMPORARY tables now validate the same as session TEMPORARY tables across these options.
Sergei Golubchik
MDEV-41467 mbstream insufficient path validation in REMOVE and RENAME chunks

* apply the check from file_entry_new() also to other file operations.
* add a Windows specific check.
Sutou Kouhei
MDEV-41285 ASAN heap-buffer-overflow mrn_get_string_between_quote/mrn_parse_table_param

Fix a heap buffer overflow on escaped string in table/index comment parameter (#1249)

`mrn_get_string_between_quote()` didn't advance `current_ptr` after it
processed an escape sequence such as `\x`. So it wrote the escaped
character repeatedly and overflowed the allocated buffer. It also didn't
terminate the extracted string with `\0` when the string had an escape
sequence.

For example, the following SQL caused a heap buffer overflow:

```sql
CREATE TABLE t1 (c INT) ENGINE=Mroonga COMMENT='engine "InnoDB\\x"';
```

This also returns `NULL` when `mrn_my_malloc()` fails.

Reported by Alice Sherepa. Found by Yuelin Wang.

Assisted-by: Claude:claude-5.5-opus
Oleksandr Byelkin
MDEV-40303 SIGSEGV in Item_field::type_handler() on PS re-execution

On PS re-execution a derived column is resolved via item->cached_table.
If fixing its scalar UNION subquery fails, the unit's prepare() error path
calls cleanup() but leaves 'prepared' set. find_field_in_view() returned
0 ("not found"), so find_field_in_tables() fell through to the generic
lookup, re-fixed the same subquery, prepare() returned early and
set_row() hit NULL fields.

Fix: return view_field_error when a view/derived field cannot be fixed
and stop the lookup on it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Georgi (Joro) Kodinov
more doxygen formatting added.
Andrei Elkin
MDEV-41214 PURGE BINARY LOGS does not delete non-active binlog files

PURGE BINARY LOGS could end with a warning instead of deleting files, as
the test below shows when run on the base of this commit. The warning
names a wrong reason. It follows an automatic purge that was refused by
the slave guard, slave_connections_needed_for_purge: the automatic purge
does not delete a binlog while it might still be needed by a slave, not
necessarily a connected one, that is while fewer than the variable's
number of slaves are connected.
Since MDEV-34504 the manual PURGE is meant to ignore the guard.
Yet it still protects a binlog that a slave is reading.

Technically this was possible because the automatic and the manual purge
share a code path, can_purge_log(), which cached the refusal and replayed
it, under the reason of the first arm below, to any later purge:

  if (is_active(name) ||
      (!is_relay_log && waiting_for_slave_to_change_binlog &&
      purge_sending_new_binlog_file == sending_new_binlog_file &&
      !strcmp(name, purge_binlog_name)))
    reason= "it is the current active binlog";

So "active" had to be read as "active or busy". The fix removes this
duality too: the two arms are now separate and have their own reasons.

The main issue is fixed by narrowing the busy arm with an additional
`!interactive &&` conjunct, so that a manual PURGE never consults the
cached refusal.

Running the test below on an unfixed 11.4 server (source tree at commit
42038e1145d) fails with "Result length mismatch" and, in part 2, this
diff against the recorded result:

  PURGE BINARY LOGS TO 'master-bin.000006';
  +Warnings:
  +Note 1375 Binary log 'master-bin.000003' is not purged because it is the current active binlog
  SHOW WARNINGS;
  Level Code Message
  +Note 1375 Binary log 'master-bin.000003' is not purged because it is the current active binlog
  show binary logs;
  Log_name File_size
  +master-bin.000003 #
  +master-bin.000004 #
  +master-bin.000005 #
  master-bin.000006 #
  master-bin.000007 #
  master-bin.000008 #

Test binlog.binlog_purge_stale_refusal_cache: the test sets
slave_connections_needed_for_purge=1, binlog_expire_logs_seconds=0 and
max_binlog_total_size=0 first and restores them at the end. It starts
with RESET MASTER so that the binlog names, 000003 and so on, do not depend
on the tests run before it in the same mtr environment. Part 1 is a control with
nothing cached; part 2 makes an automatic purge refuse 000003 (the files
must be older than binlog_expire_logs_seconds, hence --real_sleep 2 before
the rotation) and then runs PURGE BINARY LOGS TO 'master-bin.000006',
which must remove 000003..000005.

As a workaround, a PURGE could work if the following settings are made
before it, in this order:

  SET GLOBAL binlog_expire_logs_seconds=0, slave_connections_needed_for_purge=0;

The second setting invalidates the cached refusal. The first one keeps
the purge that this setting triggers from refusing and caching again.
Note that both settings change the server's policy, not only this one
PURGE: the time-based expiry and the slave guard are off until they are
restored.
Monty
MDEV-25292 Atomic CREATE OR REPLACE TABLE

Atomic CREATE OR REPLACE allows to keep an old table intact if the
command fails or during the crash. That is done by renaming the
original table to temporary name, as a backup and restoring it if the
CREATE fails. When the command is complete and logged the backup
table is deleted.

Atomic replace algorithm

Two DDL chains are used for CREATE OR REPLACE:
ddl_log_state_create (C) and ddl_log_state_rm (D).

  1. (C) Log rename of ORIG to TMP table (Rename TMP to original).
  2. Rename orignal to TMP.
  3. (C) Log CREATE_TABLE_ACTION of ORIG (drops ORIG);
  4. Do everything with ORIG (like insert data)
  5. (D) Log drop of TMP
  6. Write query to binlog (this marks (C) to be closed in
    case of failure)
  7. Execute drop of TMP through (D)
  8. Close (C) and (D)

  If there is a failure before 6) we revert the changes in (C)
  Chain (D) is only executed if 6) succeded (C is closed on
  crash recovery).

Foreign key errors will be found at the 1) stage.

Additional notes

- CREATE TABLE without REPLACE and temporary tables is not affected
  by this commit.
  set @@drop_before_create_or_replace=1 can be used to
  get old behaviour where existing tables are dropped
  in CREATE OR REPLACE.

- CREATE TABLE is reverted if binlogging the query fails.

- Engines having HTON_EXPENSIVE_RENAME flag set are not affected by
  this commit. Conflicting tables marked with this flag will be
  deleted with CREATE OR REPLACE.

- Replication execution is not affected by this commit.
  - Replication will first drop the conflicting table and then
    creating the new one.

- CREATE TABLE .. SELECT XID usage is fixed and now there is no need
  to log DROP TABLE via DDL_CREATE_TABLE_PHASE_LOG (see comments in
  do_postlock()). XID is now correctly updated so it disables
  DDL_LOG_DROP_TABLE_ACTION. Note that binary log is flushed at the
  final stage when the table is ready. So if we have XID in the
  binary log we don't need to drop the table.

- Three variations of CREATE OR REPLACE handled:

  1. CREATE OR REPLACE TABLE t1 (..);
  2. CREATE OR REPLACE TABLE t1 LIKE t2;
  3. CREATE OR REPLACE TABLE t1 SELECT ..;

- Test case uses 6 combinations for engines (aria, aria_notrans,
  myisam, ib, lock_tables, expensive_rename) and 2 combinations for
  binlog types (row, stmt). Combinations help to check differences
  between the results. Error failures are tested for the above three
  variations.

- expensive_rename tests CREATE OR REPLACE without atomic
  replace. The effect should be the same as with the old behaviour
  before this commit.

- Triggers mechanism is unaffected by this change. This is tested in
  create_replace.test.

- LOCK TABLES is affected. Lock restoration must be done after new
  table is created or TMP is renamed back to ORIG

- Moved ddl_log_complete() from send_eof() to finalize_ddl(). This
  checkpoint was not executed before for normal CREATE TABLE but is
  executed now.

- CREATE TABLE will now rollback also if writing to the binary
  logging failed. See rpl_gtid_strict.test

backup ddl log changes

- In case of a successfull CREATE OR REPLACE we only log
  the CREATE event, not the DROP TABLE event of the old table.

ddl_log.cc changes

  ddl_log_execute_action() now properly return error conditions.
  ddl_log_disable_entry() added to allow one to disable one entry.
  The entry on disk is still reserved until ddl_log_complete() is
  executed.

On XID usage

  Like with all other atomic DDL operations XID is used to avoid
  inconsistency between master and slave in the case of a crash after
  binary log is written and before ddl_log_state_create is closed. On
  recovery XIDs are taken from binary log and corresponding DDL log
  events get disabled.  That is done by
  ddl_log_close_binlogged_events().

On linking two chains together

  Chains are executed in the ascending order of entry_pos of execute
  entries. But entry_pos assignment order is undefined: it may assign
  bigger number for the first chain and then smaller number for the
  second chain. So the execution order in that case will be reverse:
  second chain will be executed first.

  To avoid that we link one chain to another. While the base chain
  (ddl_log_state_create) is active the secondary chain
  (ddl_log_state_rm) is not executed. That is: only one chain can be
  executed in two linked chains.

  The interface ddl_log_link_chains() was defined in "MDEV-22166
  ddl_log_write_execute_entry() extension".

Atomic info parameters in HA_CREATE_INFO

  Many functions in CREATE TABLE pass the same parameters. These
  parameters are part of table creation info and should be in
  HA_CREATE_INFO (or whatever). Passing parameters via single
  structure is much easier for adding new data and
  refactoring.

Aria changes:
- Fixed issue in Aria engine with CREATE + locked tables
  that data was not properly commited in some cases in
  case of crashes.

InnoDB related changes (by Marko Mäkelä):
- table_name_t::is_create_or_replace(): A new predicate to check for
  CREATE OR REPLACE TABLE will rename an old table to
  and eventually drop after creating the replacement.
- dict_table_t::parse_name(): Do acquire MDL on #sql-create- names
  for partitioned tables.
- dict_table_rename_in_cache(): On CREATE OR REPLACE TABLE ... SELECT,
  forget the original dict_table_t::mdl_name so that purge will
  acquire MDL on the #sql-create- name instead. In this way, the
  MDL_EXCLUSIVE that the CREATE OR REPLACE TABLE holds on the
  user-visible name will not unnecessarily block any purge of old history
  until the very end when the #sql-create- table will be dropped.
- ha_innobase::delete_table(): Do not check FOREIGN KEY consistency
  when dropping an #sql-create- table.
- row_rename_table_for_mysql(): Update SYS_FOREIGN.ID also
  when renaming to #sql-create- in order to avoid any
  duplicate key error when CREATE OR REPLACE TABLE is
  creating some FOREIGN KEY constraints by names
  that existed in the old table.

Other changes:
- Removed some auto variables in log.cc for better code readability.
- Fixed old bug that CREATE ... SELECT would not be able to auto repair
  a table that is part of the SELECT.
- Marked MyISAM that it does not support ROLLBACK (not required but
  done for better consistency with other engines).
- maria_create_trn_for_mysql() does not register a new transaction
  handler for commits. This was needed to ensure create or replace
  will not end with an active transaction.
- We do not get anymore warnings about "Engine not supporting atomic
  create" when doing a legal CREATE OR REPLACE on a table with
  foreign key constraints.
- Updated VIDEX engine flags to disable CREATE SEQUENCE.
- Removed mysql_mutex_unlock(&LOCK_gdl) / mysql_mutex_lock(&LOCK_gdl)
  around calls to binlog as these are unsafe. The binlog code uses
  global variables that needs protection from other caller.
- EITS data is preserved if create or replace fails if
  drop_before_create_or_replace=OFF. If ON, then create or replace
  will drop EITS before the drop of the original table (as before).
- Using CREATE OR REPLACE on a encrypted table that the user cannot
  decrypt will fail instead of replacing the encrypted table.
  The encrypted table will unchanged.

Known issues:
- One cannot use create or replace on an InnoDB tables that has foreign
  key references point to it
- CREATE OR REPLACE TEMPORARY table is not full atomic. Any conflicting
  table will always be dropped before creating a new one. (Old behaviour).

Bug fixes related to this MDEV:
MDEV-36435 Assertion failure in finalize_locked_tables()
MDEV-36439 Assertion `thd_arg->lex->sql_command != SQLCOM_CREATE_SEQUENCE...
MDEV-36498 Failed CoR in non-atomic mode no longer generates DROP in RBR...
MDEV-36508 Temporary files #sql-create-....frm occasionally stay after
          crash recovery
MDEV-38479 Crash in CREATE OR REPLACE SEQUENCE when new sequence cannot
          be created
MDEV-36497 Assertion failure after atomic CoR with Aria under lock in
          transactional context
MDEV-36501 EITS data is lost after failed attempt to CREATE OR REPLACE
          table
MDEV-36493 Atomic CREATE OR REPLACE ... SELECT blocks InnoDB purge
MDEV-39367 MSAN/valgrind errors in temp_file_size_cb_func,
          main.tmp_space_usage fails
MDEV-39446 Atomic CREATE OR REPLACE fails if a table cannot be decrypted
MDEV-40776 Atomic CREATE OR REPLACE silently breaks the foreign key
MDEV-40765 Assertion `"unexpected references" == 0' failed upon failing
          CREATE OR REPLACE
MDEV-40994 Atomic CoR: Transaction not registered for MariaDB 2PC, but
          transaction is active

Reverted commits:
- MDEV-36685 "CREATE-SELECT may lose in binlog side-effects of
  stored-routine" as it did not take into account that it safe to
  clear binlogs if the created table is non transactional and there
  are no other non transactional tables used.
  This was done because it caused extra logging when it is not
  needed (not using any non transactional tables) and it also did
  not solve side effects when using statement based loggging.
Sergei Golubchik
MDEV-41467 mbstream insufficient path validation in REMOVE and RENAME chunks

apply the check from file_entry_new() also to other file operations
Sergei Golubchik
MDEV-41253 RPM %pre scriptlet unconditionally resets a pre-existing mysql user's home directory to /nonexistent

keep resetting to not writable, but use an existing path
Monty
Added --debug-dbug option to mysqltest.cc

This was to get rid of warnings when using mtr --debug
Sutou Kouhei
Fix auto directory creation for absolute mroonga_database_path_prefix (#1166)

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

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

Assisted-by: Claude:claude-5.5-opus
Oleksandr Byelkin
MDEV-40303 SIGSEGV in Item_field::type_handler() on PS re-execution

On PS re-execution a derived column is resolved via item->cached_table.
If fixing its scalar UNION subquery fails, the unit's prepare() error path
calls cleanup() but leaves 'prepared' set. find_field_in_view() returned
0 ("not found"), so find_field_in_tables() fell through to the generic
lookup, re-fixed the same subquery, prepare() returned early and
set_row() hit NULL fields.

Fix:
- find_field_in_view()/find_field_in_natural_join() return the new
  field_fix_error when the found field cannot be fixed, and name
  resolution stops on it.
- st_select_lex_unit::prepare() fails for a unit whose preparation
  already failed in this execution instead of reporting it prepared.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Sergei Golubchik
workaround for https://bugzilla.redhat.com/show_bug.cgi?id=2390105
PranavKTiwari
MDEV-28610 : Assertion  marked_for_read() failed upon range select with virtual column in index.
Problem:
Executing a range select using an index that includes virtual/generated columns
(e.g. SELECT ... WHERE c BETWEEN ... ORDER BY d) could trigger:

Assertion 'marked_for_read()' failed in Field access during execution.

Cause:
The keyread initialization path was populating table->read_set using
mark_index_columns(), which follows the non-recursive index marking path.
This only marks direct index fields and does not resolve dependencies of
virtual/generated columns.

As a result, when an index contained virtual columns, their dependent base
columns were not included in read_set, leading to invalid access during
later evaluation of virtual columns.

Fix:
Replace mark_index_columns() with mark_index_columns_for_read() in the
keyread initialization path. This ensures the recursive read-marking logic is
used, so virtual/generated column dependencies are correctly propagated into
read_set before execution.
Sergei Golubchik
MDEV-41431 LOAD_FILE checks for is_secure_file_path() one path but opens another
bsrikanth-mariadb
MDEV-41243, MDEV-41273 Don't freeze mem_root after engine pushdown

When a statement is pushed down to an engine, the once-per-statement
part of the optimization (e.g. the first_cond_optimization part of
JOIN::optimize(), or the whole of JOIN::optimize() for a pushed down
UNION) is skipped. Re-executing the same prepared statement or stored
routine without pushdown then allocated from a mem_root already marked
ROOT_FLAG_READ_ONLY, hitting an assertion in alloc_root().

Add LEX::dont_freeze_mem_root, set by the pushdown_handler and
derived_handler constructors so it covers every engine implementing
them. Prepared_statement::execute_loop(), sp_head::execute() (through
sp_head::dont_freeze_mem_root) and the SP instruction reparse path no
longer freeze the mem_root of such statements. The flag is only
declared and used in PROTECT_STATEMENT_MEMROOT builds.

The flag is per execution for prepared statements:
Prepared_statement::execute_loop() clears it after each execution, so
the mem_root is frozen again after the first later execution that is
not pushed down. For a stored routine the instruction's LEX keeps the
flag, so once one instruction has been pushed down the routine's
mem_root stays unfrozen, even if later executions are not pushed down,
unless the routine is re-parsed into a new LEX.

Add tests for prepared SELECT, UNION, UPDATE and DELETE, prepared
EXPLAIN of a pushed UNION, derived tables, stored procedures,
functions, triggers, cursors and metadata-invalidation reparse, with
pushdown switched on and off. Most prepared statement and routine
tests check the statements received by the remote server, or EXPLAIN,
to verify that pushdown actually happened.
Vladislav Vaintroub
MDEV-39150 Some data conversion macros fail to use memcpy()

MDEV-37788 converted the uintNkorr() and intNstore() macros to use
memcpy() and byte swap intrinsics, but the floating point and short/long
conversion macros in big_endian.h and myisampack.h still accessed data
one byte at a time, and those in little_endian.h were a mix of both.
Compilers may emit slow byte-at-a-time loads and stores for such code.

Reimplement the macros with memcpy(), and with MY_BSWAP32/MY_BSWAP64
where the byte order differs from the host. big_endian.h and
little_endian.h no longer differ, so move the macros to my_byteorder.h
and remove the two headers, which are no longer installed. Implement
mi_float4store() etc. in myisampack.h with the same helper macros.

Remove the unused ulongget() macro, and the code for the mixed-endian
floating point layout (a little-endian CPU with big-endian floating
point word order) from the macros, change_double_for_sort() and dtoa.c.
It only applied to the obsolete ARM FPA format.

Reimplement mach_double_read(), mach_double_write(), mach_float_read()
and mach_float_write() in InnoDB with float8get(), float8store(),
float4get() and float4store(), instead of copying bytes in a loop.

The stored formats do not change. The unit test byte_order-t now checks
the byte layout of the floating point macros and the sign extension of
the native byte order macros, so no MTR test is added.
Kristian Nielsen
MDEV-41217: Inefficient memory management by parallel slave

Draft patch / proof-of-concept.

This patch splits the rpl_group_info into two parts. A small part that
contains only the information necessary in the queue of events sent from the
SQL driver thread to parallel replication worker threads is made separate
and pointed to by rpl_group_info::q.

This greatly reduces the memory requirements for the queued event groups,
especially when the slave is lagging and there are a lot of event groups
queued (eg. due to large --slave-parallel-max-queued).

Now the main rpl_group_info object only exists once per worker thread (and
once in the SQL driver thread).

Signed-off-by: Kristian Nielsen <[email protected]>
Sergei Golubchik
MDEV-41458 Assertion `n > 0 && n < SINUSES_CALCULATED*2+1' failed in get_n_sincos()

With tiny *ex and *ey the sum of squares underflows and q becomes inf,
use hypot() which is under- and overflow safe.

Also, fix ab/(d*d) divison, for good measure
Vladislav Vaintroub
MDEV-39533 Resolve reparse points and enforce MY_NOSYMLINKS on Windows

On Windows, my_realpath() only called GetFullPathName(), does not resolve
symlinks, junctions or mount points, unlike POSIX realpath(). At the
same time, my_open() and my_delete() ignored MY_NOSYMLINKS entirely,
so the symlink-attack protection used for MyISAM/Aria's DATA
DIRECTORY/INDEX DIRECTORY (mi_open()/ma_open(),
my_handler_delete_with_symlink()) was silently absent on Windows.

Fix my_realpath() to actually resolve reparse points: open the
path with CreateFile(), which follows them, and read back the handle's
fully resolved path with GetFinalPathNameByHandle(). As a result,
a missing path now correctly returns 1/ENOENT on Windows too, matching
Linux's realpath()-based behavior, instead of always returning 0.

Make my_open() and my_delete() honor MY_NOSYMLINKS on Windows.
Windows has no per-path-component O_NOFOLLOW equivalent, so instead
this mirrors the HAVE_REALPATH branch of the POSIX
NOSYMLINK_FUNCTION_BODY macro: the caller-supplied name (expected to
already be my_realpath()-resolved) is compared against the actually
opened handle's resolved path, and rejected with ENOTDIR -- the same
errno POSIX uses for this exact "not already canonical" condition --
on a mismatch, whether caused by a TOCTOU symlink swap or by the name
never having been fully resolved to begin with.

Known limitation: GetFinalPathNameByHandle(FILE_NAME_NORMALIZED), used
by both my_realpath() and MY_NOSYMLINKS verification, can fail on some
SMB shares (an intermediate directory denying list/read access while
still allowing traverse). When that happens, both fall back to the
weaker FILE_NAME_OPENED query: my_realpath() still succeeds, but
MY_NOSYMLINKS verification is weaker, since FILE_NAME_OPENED may not
fully resolve reparse points. A one-time warning naming the affected
path is raised the first time this happens.

MyISAM/Aria's DATA DIRECTORY/INDEX DIRECTORY data-file open only
requests MY_NOSYMLINKS when O_NOFOLLOW is set in share->data_mode, and
O_NOFOLLOW was plain 0 on Windows (no such real open() flag there), so
the data file was never actually protected even with the above in
place -- only the index file was. Give O_NOFOLLOW a real, reserved bit
on Windows (clear of every _O_* flag the UCRT defines), so the
existing data_mode gating works as intended; it remains a harmless
no-op as a real open() flag, same as before.

As part of enforcing MY_NOSYMLINKS for my_delete(), my_win_unlink()
(formerly in my_delete.c) is rewritten and moved to my_winfile.cc: it
opens the file once, verifies no symlinks before removing it, and
only then decides how to remove it (posix-semantics delete, or
rename-then-classic-dispose for filesystems without posix-semantics
delete, renaming back if dispose still fails). This drops the old
DeleteFile() fast path for a reparse-point leaf and its separate
sharing-violation retry loop, no longer grants FILE_SHARE_DELETE on
its own handle, and reports real posix-delete errors (e.g. a
read-only file) instead of masking them with a fallback attempt.

Add unittest/mysys/my_symlink-t.c (junction resolution and
MY_NOSYMLINKS enforcement for my_open()/my_delete()) and extend
unittest/mysys/my_delete-t.c with my_win_unlink()'s own fallback paths
(posix-semantics failure, rename failure, read-only files).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
PranavKTiwari
MDEV-38839: Assertion `(thd->state_flags & Open_tables_state::BACKUPS_AVAIL) || !thd->has_pending_row_events()` failed in close_thread_tables on CREATE TABLE

Problem:
CREATE TABLE ... SELECT ... FOR UPDATE involving a MyISAM temporary table can trigger an assertion in close_thread_tables() when binary logging is enabled in MIXED mode.

Cause:
MyISAM temporary tables do not support row-level locking, so SELECT ... FOR UPDATE acquires a write lock even when the access is read-only. This causes the table to be incorrectly classified as a write operation, preventing binlog_truncate_trx_cache() from running and eventually triggering the assertion.

Fix:
Update decide_logging_format() to use tbl->updating to distinguish actual table modifications from read-only accesses. For read-only access to temporary non-transactional tables, mark the statement as STMT_READS_TEMP_NON_TRANS_TABLE instead of treating it as a write operation. This prevents incorrect write classification and avoids the assertion failure.
Vladislav Vaintroub
MDEV-39150 Some data conversion macros fail to use memcpy()

MDEV-37788 converted the uintNkorr() and intNstore() macros to use
memcpy() and byte swap intrinsics, but the floating point and short/long
conversion macros in big_endian.h and myisampack.h still accessed data
one byte at a time, and those in little_endian.h were a mix of both.
Compilers may emit slow byte-at-a-time loads and stores for such code.

Reimplement the macros with memcpy(), and with MY_BSWAP32/MY_BSWAP64
where the byte order differs from the host. big_endian.h and
little_endian.h no longer differ, so move the macros to my_byteorder.h
and remove the two headers, which are no longer installed. Implement
mi_float4store() etc. in myisampack.h with the same helper macros.

Remove the unused ulongget() macro, and the code for the mixed-endian
floating point layout (a little-endian CPU with big-endian floating
point word order) from the macros, change_double_for_sort() and dtoa.c.
It only applied to the obsolete ARM FPA format.

Reimplement mach_double_read(), mach_double_write(), mach_float_read()
and mach_float_write() in InnoDB with float8get(), float8store(),
float4get() and float4store(), instead of copying bytes in a loop.

The stored formats do not change. The unit test byte_order-t now checks
the byte layout of the floating point macros and the sign extension of
the native byte order macros, so no MTR test is added.
Oleg Smirnov
MDEV-32412 Pushdown from HAVING: Item_func is immutable while arguments are not

Fix-up for commit e97560eac03 (MDEV-28958), which made set_extraction_flag()
ignore basic constants so that the read-only Item_true/Item_false singletons
are never written to. Because of that, the callers that mark a subtree with
MARKER_IMMUTABLE before pushing a condition from HAVING into WHERE cannot
mark basic constants inside it.

Item::cleanup_excluding_immutables_processor() did not know about this
exception and cleaned such items up, unfixing them while their marked parents
stayed fixed. fix_fields() does not descend into fixed items, so the constant
was left unfixed and Item_direct_view_ref::used_tables() later dereferenced a
NULL null_ref_table. Skip basic constants there too.
Sergei Golubchik
MDEV-39624 storage/connect/CMakeLists.txt: unguarded generator expression variable causes fatal error at cmake generate phase
Aleksey Midenkov
MDEV-38839 table_list->updating flag comment
Sergei Golubchik
MDEV-39625 plugin/auth_pam/testing/CMakeLists.txt breaks INSTALL_MYSQLTESTDIR= suppression
Khaled Riyad
MDEV-41150 mariadb client: Ctrl-C does not interrupt tab separated result output

Ctrl-C sets interrupted_query and sends KILL QUERY to the server, but the
result is already fetched into the client by then, so killing the query
cannot stop the output. Only the printing loop can, by checking
interrupted_query.

print_table_data(), print_table_data_html(), print_table_data_xml() and
print_table_data_vertically() check it, print_tab_data() did not, so the
output of -s, -N and -B could not be interrupted.

Add the same check to print_tab_data().

No test case: the suite drives the client through a pty with socat, where
0x03 is not turned into a signal, and there is no other way in the suite to
signal a client while it is printing.
PranavKTiwari
MDEV-test Remove tests failing on MSAN memory limits
Monty
ha_table_exists() cleanup and improvement

This is part of MDEV-25292 Atomic CREATE OR REPLACE TABLE.

Removed default values for arguments, added flags argument to specify
filename flags (FN_TO_IS_TMP, FN_FROM_IS_TMP) and forward the flag to
build_table_name().

Original patch from: Aleksey Midenkov <[email protected]>
Monty
MDEV-31138 Enable the test spider/bugfix.mdev_29676
PranavKTiwari
MDEV-26820 Assertion 'marked_for_read()' failed upon SELECT with VALUE(virtual column)
Problem:
Item_insert_value::fix_fields() created a temporary field
without preserving vcol_info. As a result, VALUE()/VALUES()
on virtual columns lost dependency metadata and could trigger:

Assertion `marked_for_read()' failed during virtual column evaluation.

Cause:
The temporary Field_string copied field_index but did not copy virtual column metadata from the original field.

Fix:
Preserve vcol_info when creating temporary fields in Item_insert_value::fix_fields() so virtual column dependency
tracking remains intact.
Monty
MDEV-23298 Assertion `table_list->prelocking_placeholder == TABLE_LIST::PRELOCK_NONE' failed in check_lock_and_start_stmt on CREATE OR REPLACE TABLE

Fixed by removing wrong assert

Review: Sanja Byelkin
Vladislav Vaintroub
MDEV-39533 Resolve reparse points and enforce MY_NOSYMLINKS on Windows

On Windows, my_realpath() only called GetFullPathName(), does not resolve
symlinks, junctions or mount points, unlike POSIX realpath(). At the
same time, my_open() and my_delete() ignored MY_NOSYMLINKS entirely,
so the symlink-attack protection used for MyISAM/Aria's DATA
DIRECTORY/INDEX DIRECTORY (mi_open()/ma_open(),
my_handler_delete_with_symlink()) was silently absent on Windows.

Fix my_realpath() to actually resolve reparse points: open the
path with CreateFile(), which follows them, and read back the handle's
fully resolved path with GetFinalPathNameByHandle(). As a result,
a missing path now correctly returns 1/ENOENT on Windows too, matching
Linux's realpath()-based behavior, instead of always returning 0.

Make my_open() and my_delete() honor MY_NOSYMLINKS on Windows.
Windows has no per-path-component O_NOFOLLOW equivalent, so instead
this mirrors the HAVE_REALPATH branch of the POSIX
NOSYMLINK_FUNCTION_BODY macro: the caller-supplied name (expected to
already be my_realpath()-resolved) is compared against the actually
opened handle's resolved path, and rejected with ENOTDIR -- the same
errno POSIX uses for this exact "not already canonical" condition --
on a mismatch, whether caused by a TOCTOU symlink swap or by the name
never having been fully resolved to begin with.

Known limitation: GetFinalPathNameByHandle(FILE_NAME_NORMALIZED), used
by both my_realpath() and MY_NOSYMLINKS verification, can fail on some
SMB shares (an intermediate directory denying list/read access while
still allowing traverse). When that happens, both fall back to the
weaker FILE_NAME_OPENED query: my_realpath() still succeeds, but
MY_NOSYMLINKS verification is weaker, since FILE_NAME_OPENED may not
fully resolve reparse points. A one-time warning naming the affected
path is raised the first time this happens.

MyISAM/Aria's DATA DIRECTORY/INDEX DIRECTORY data-file open only
requests MY_NOSYMLINKS when O_NOFOLLOW is set in share->data_mode, and
O_NOFOLLOW was plain 0 on Windows (no such real open() flag there), so
the data file was never actually protected even with the above in
place -- only the index file was. Give O_NOFOLLOW a real, reserved bit
on Windows (clear of every _O_* flag the UCRT defines), so the
existing data_mode gating works as intended; it remains a harmless
no-op as a real open() flag, same as before.

As part of enforcing MY_NOSYMLINKS for my_delete(), my_win_unlink()
(formerly in my_delete.c) is rewritten and moved to my_winfile.cc: it
opens the file once, verifies no symlinks before removing it, and
only then decides how to remove it (posix-semantics delete, or
rename-then-classic-dispose for filesystems without posix-semantics
delete, renaming back if dispose still fails). This drops the old
DeleteFile() fast path for a reparse-point leaf and its separate
sharing-violation retry loop, no longer grants FILE_SHARE_DELETE on
its own handle, and reports real posix-delete errors (e.g. a
read-only file) instead of masking them with a fallback attempt.

Add unittest/mysys/my_symlink-t.c (junction resolution and
MY_NOSYMLINKS enforcement for my_open()/my_delete()) and extend
unittest/mysys/my_delete-t.c with my_win_unlink()'s own fallback paths
(posix-semantics failure, rename failure, read-only files).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Sergei Golubchik
MDEV-41449 ASAN server crash on corrupted frm

make sure the declared (not actual) file length is not too small
Alessandro Vetere
fixup! MDEV-33966: buf_page_make_young() is a contention point
Sutou Kouhei
MDEV-41287 ASAN: stack-buffer-overflow in strcpy/mrn::DatabaseRepairer::detect_paths/mrn::DatabaseRepairer::each_database

Fix a buffer overflow with long mroonga_database_path_prefix (#1159)

Reported by Yuelin Wang. Thanks!!!

We used fixed size buffers (MRN_MAX_PATH_SIZE) for database paths built
from mroonga_database_path_prefix. So a long
mroonga_database_path_prefix caused a buffer overflow.

This uses std::string for them. We don't need to check path length in
Mroonga because Groonga reports an error for too long path.

Assisted-by: Claude:claude-5.5-opus
Sergei Golubchik
cleanup: put "bad frm" tests in one file