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
Dave Gosselin
MDEV-41251:  Keep the original cache in a copy of an item tree

A copy of an item tree now holds the original Item_cache instead of a
new one, and this includes a row cache, which could not be copied
before.  With t0 holding (1,3), (2,2) and (3,7), the IN subquery over a
split materialized table in the test returned only (1,3), but the same
query without splitting returns (1,3) and (2,2).

The equality pushed into the split table held a copy of the cache of
the IN predicate.  Item_in_optimizer stores a new value into its own
cache for each outer row, yet nothing stored into the copy, so the copy
kept the value of the first row.  The walk that marks the fields of the
pushed equality as dependent no longer enters caches, whose example
belongs to the select of the cache owner.  The debug check of a copy
accepts the shared cache, and the item_cache_clones debug flag now
makes a shallow copy of each new cache.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
DerZc
MDEV-40689 Wrong result: BIT_AND/BIT_OR/BIT_XOR in WINDOW functions over a frame containing NULL

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

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

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

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

Bug report: https://jira.mariadb.org/browse/MDEV-40689
Aleksey Midenkov
MDEV-25529 Fix to_string() OOM return semantics for temporal types

Temporal_hybrid::to_string() returned the destination String with a stale
length when String::alloc() failed, instead of signalling the failure. Return
NULL on allocation failure.

Apply the same fix to the sibling to_string() methods of Interval_DDhhmmssff,
Time and Datetime, which shared the identical flaw, so all four report OOM
consistently. Callers already treat a NULL return as the error/invalid result,
so no caller that was correct before is affected.
Yuchen Pei
Allow a covering index scan for a SELECT ... FOR UPDATE under a full-scan table lock

(TODO: improve commit message)

MDEV-24813 introduced a switch innodb_table_lock_on_full_scan that
places a table lock on an innodb table for some unconditional SELECT
statements.

With a full table lock, and when doing a covering scan, there is no
need to acquire clustered locks. This patch does so for X-locks.

TODO: add code comments and tests

Co-Authored-By: Claude Opus 5 <[email protected]>
Dave Gosselin
MDEV-41211 Remove unused index_read_idx() from both Federated engines

ha_federated::index_read_idx() and ha_federatedx::index_read_idx()
have no callers and do not override a handler method.  Remove them,
and remove the sentence in the comment on each index_read() that says
index_read() calls it.  Comments that describe index_read_idx() now
name index_read() or index_read_idx_map(), whichever does that read.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Alexey Botchkov
MENT-2227 auth_pam_tool zombie processes (Follow up of "fixed" MENT-1443).

As the auth_pam_tool claims root privileges, the mariadbd can't kill
it if it hangs.
So use setresuid() call instead to save the caller_uid.
Also wait for longer after the kill(SIGKILL).
Dave Gosselin
MDEV-41303:  rand() in a semi-join subquery is checked on outer rows

Do not merge a subquery into its parent as a semi-join when it has
the UNCACHEABLE_RAND flag, which RAND() and ROWNUM set.  Derived
tables already follow this rule.  ROWNUM sets the same flag, so this
patch replaces the check for ROWNUM with a check for UNCACHEABLE_RAND.

Previously, converting an IN subquery to a semi-join moved its WHERE
into the parent WHERE.  A condition there such as rand(1) < 0.09
doesn't rely on any columns, so it is attached to the last table of
the join order that is outside any materialized semi-join.  With
SJ-Materialization it was checked once for each outer row instead of
once for each row of the subquery, and the query returned a wrong
count.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Rex Johnston
MDEV-41179 MAX_KEY_PARTS ranges in select causing SEGV

When a select containing 32 ranges is made on a table containing a
compound key with 32 parts, the range optimizer can run off the end
of a stack variable, invalidly overwriting subsequent stack variables.

In the struct st_sel_arg_range_seq, we have an array
  RANGE_SEQ_ENTRY stack[MAX_REF_PARTS];

MAX_REF_PARTS is 32.

check_quick_select
  / sel_arg_range_seq_init
    initialises stack[0] as NOT a key part
  / sel_arg_range_seq_next
    iterates through the key parts, adding key part n to stack[n+1]

key part #32 gets referenced by step_down_to(), setting seq->i off the
end of the array.

Fix: RANGE_SEQ_ENTRY stack[MAX_REF_PARTS+1];

The above change exposed an issue with key length calculation on
MS Windows.  Calling make_prev_keypart_map(32) caused the resultant
bitmap to be calculated as (1UL << 32) - 1.  Using the MSVC compiler
this resulted in an empty key length calculation during
handler::index_read_map, causing an assertion in ha_innobase::index_read().

As we only need 32 bits to represent our key map, we change the type thus
-typedef ulong key_part_map;
+typedef uint32 key_part_map;

We correct make_keypart_map() and make_prev_keypart_map() to call our
overflow safe my_set_bits().  We also correct bka_range_seq_next()
and bkah_range_seq_next() to use make_prev_keypart_map().

We also add some DBUG_ASSERTS in key_part_map processing elsewhere,
exposing some issues in our BNLH implementation.  We cap the number of
keyuse parts here, altering the explain output of 2 of our tests.

Numerous places needed bit shift operations altered to use
make*keymap_part and various format strings needed to be corrected.
Aleksey Midenkov
MDEV-25529 Timestamp_string for printing timestamps

Add a Timestamp_string helper that formats a Timestamp in the session time
zone for use in warning and error messages, plus THD::timestamp_to_string()
and a Temporal_hybrid constructor behind it. Reuse the existing Timestamp
type rather than introducing a new one. Use it when printing STARTS and the
history range.

Rename the error symbol ER_PART_STARTS_BEYOND_INTERVAL to
WARN_VERS_STARTS_BEYOND_INTERVAL and extend its message: it now takes the
STARTS timestamp and the query timestamp as arguments, so the number of
format arguments changes from one to three. The error number (4164) is
unchanged, so this is not an ABI break, but libmariadb still exports the
old symbol name for that number until its submodule is updated.
Aleksey Midenkov
MDEV-25529 set_up_default_partitions() ER_OUT_OF_RESOURCES error
Khaled Riyad
MDEV-38861 heap-use-after-free in Prepared_statement::execute()

DROP PROCEDURE and CREATE OR REPLACE PROCEDURE executed from inside the
routine itself removed it from the SP cache. sp_head::destroy() then freed
the memory root that the running sp_head, its LEX and its instructions
live in, and the caller kept using them.

Skip the removal while the routine is being executed. sp_cache_invalidate()
above has already bumped the cache version, so the stale entry is removed by
the next lookup, after IS_INVOKED has been cleared.
Dave Gosselin
MDEV-41211 Federated multi-table DELETE keeps a const table row

A multi-table DELETE on a FEDERATED or FederatedX table went wrong
when a primary key lookup made the target a const table.  The
optimizer reads a const table's row through index_read_idx_map(),
whose default implementation ends the index scan and frees the result
set.  The server asks for the row's position later, during execution,
so the saved position was empty.  FederatedX skipped the row and
FEDERATED crashed in rnd_pos().

Both engines now override index_read_idx_map() so that the lookup
leaves its result set open, as index_read() does.  position() then
records a valid position, and the result set is freed at the end of
the statement.  FEDERATED's reset() now also clears stored_result,
which otherwise pointed at a freed result set and was freed again
when the table was closed.

Tests include a multitable UPDATE with a const target, which crashed
both engines before the fix.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Yuchen Pei
Allow a covering index scan for a locking SELECT under a full-scan table lock

Follow-up to MDEV-24813 (innodb_table_lock_on_full_scan) and MDEV-40805.

ha_innobase::build_template() retrieves the whole clustered index record
whenever select_lock_type is LOCK_X, and row_search_with_covering_prefix()
refuses the covering-index optimisation for the same reason. As a result a
covering secondary index scan such as

  SELECT sec, id FROM t1 FOR UPDATE

visits the clustered index once per scanned row, while the same scan with
LOCK IN SHARE MODE stays inside the secondary index. On a one million row
table that is a million extra clustered index lookups.

Only part of that work is inherent to LOCK_X. UPDATE and DELETE do need the
clustered index record, because they are going to write it. A plain locking
SELECT does not: it visits the clustered index only to place the per-row
exclusive lock that gives SELECT ... FOR UPDATE its row level exclusivity.
When innodb_table_lock_on_full_scan made us take a table level LOCK_X for
the whole scan, that per-row lock is redundant, because the table lock is
already mutually exclusive with any other transaction's LOCK_IX, and hence
with any record lock or implicit exclusive lock in the table.

Introduce row_prebuilt_t::full_scan_covering_read, set in
ha_innobase::extra_opt() next to full_table_scan and only when the statement
is a plain SELECT outside the HANDLER interface, and skip the LOCK_X
restriction in both places when it is set. The flag is never set unless
full_table_scan is set, so row level locking behaviour is unchanged when
innodb_table_lock_on_full_scan is off.

Whether a column outside the scanned index is needed is still decided by the
existing logic in build_template(), so SELECT pad ... FOR UPDATE continues to
read the clustered index.

Co-Authored-By: Claude Opus 5 <[email protected]>

fixup: keep the clustered index visit under snapshot isolation

innodb.lock_isolation 'table_lock' failed in the MDEV-33802 section:

  SELECT * FROM t FORCE INDEX (b) FOR UPDATE

succeeded where ER_CHECKREAD was expected. On t(a INT PRIMARY KEY,
b INT UNIQUE) the secondary index b stores (b, a), so SELECT * is
covered by it, and the previous commit let a locking SELECT take the
covering path under a full-scan table LOCK_X.

Placing the record lock is not the only thing the clustered index visit
does. With innodb_snapshot_isolation and a read view already open,
lock_clust_rec_read_check_and_lock() also reads the clustered record's
DB_TRX_ID and returns DB_RECORD_CHANGED when the read view cannot see
it. Skipping the clustered index skips that check, so the statement
silently locked a row it should have refused.

The table-level lock does not substitute for the check. It gives
exclusivity against concurrent transactions, whereas this reports a
change that committed before the lock was taken and is invisible to an
older read view. DB_TRX_ID is only stored in the clustered index record,
so the check cannot be answered from a secondary index record alone.

Keep visiting the clustered index whenever snapshot isolation is active
and a read view is open. A plain locking SELECT that opens no read view,
which is the case the optimisation targets, is unaffected.

Co-Authored-By: Claude Opus 5 <[email protected]>
Aleksey Midenkov
MDEV-25529 cleanup for vers_set_starts() and starts_clause
Aleksey Midenkov
MDEV-25529 Auto-create: Pre-existing historical data is not partitioned as specified by ALTER

Adds logic into prep_alter_part_table() for AUTO to check the history
range (vers_get_history_range()) and based on (max_ts - min_ts)
difference compute the number of created partitions and set STARTS
value to round down min_ts value (vers_set_starts()) if it was not
specified by user or if the user specified it incorrectly. In the
latter case it will print warning about wrongly specified user value.

In case of fast ALTER TABLE, f.ex. when partitioning already exists,
the above logic is ignored unless FORCE clause is specified. When user
specifies partition list explicitly the above logic is ignored even
with FORCE clause.

vers_get_history_range() detects if the index can be used for row_end
min/max stats and if so it gets it with ha_index_first() and
HA_READ_BEFORE_KEY (as it must ignore current data). Otherwise it does
table scan to read the stats. There is test_mdev-25529 debug keyword
to check the both and compare results. A warning is printed if the
algorithm uses slow scan.

Static key_cmp was renamed to key_eq to resolve compilation after
key.h was included as key_cmp was already declared there.
Aleksey Midenkov
MDEV-25529 converted COMBINE macro to interval2usec inline function
drrtuy
MDEV-40957 MTR  tests to cover DML statements in a replicated setup.
Marko Mäkelä
Merge
Dave Gosselin
MDEV-31180:  MyISAMMRG Crash on UPDATE of an updateable VIEW

Attach the children of a MERGE table once per statement, and keep the
value of pos_in_table_list for a MERGE table on subsequent executions
of a prepared statement.
Mohammad Tafzeel Shams
MDEV-41242 : Fix resource leaks on InnoDB/mariabackup error paths found by Infer

Several error-handling paths returned without releasing a resource
already acquired earlier in the function, or checked the wrong handle
entirely, risking use of an unopened handle.

Changes:
- SysTablespace::read_lsn_and_check_flags(): close the datafile handle
  on header-validation failure.
- xb_process_datadir(): check the freshly opened `dir` handle instead
  of the stale `dbdir`, fixing a handle leak and a possible use of an
  unopened directory handle.
- wsrep.cc / xb_load_list_file(): close file handles before die(), and
  null-check fopen() results in wsrep.cc.
- datadir_iter_new(): free datadir_path and destroy the mutex on the
  os_file_opendir() failure path.
Sergei Golubchik
extend copilot review insttructions with AI attribution policy
Brad Smith
crc32c: check elf_aux_info() return value in ppc64 probe

elf_aux_info(3) leaves the output buffer unmodified on failure, so
ignoring the return value could test an uninitialized cpufeatures and
wrongly enable the POWER8 vector-crypto path.

Treat failure as "no features" so the probe falls back to the generic
implementation.
Yuchen Pei
MDEV-41351 Allow a covering index scan for a SELECT ... FOR UPDATE under a full-scan table lock

(TODO: improve commit message)

MDEV-24813 introduced a switch innodb_table_lock_on_full_scan that
places a table lock on an innodb table for some unconditional SELECT
statements.

With a full table lock, and when doing a covering scan, there is no
need to acquire clustered locks. This patch does so for X-locks.

TODO: add code comments and tests

Co-Authored-By: Claude Opus 5 <[email protected]>
bsrikanth-mariadb
MDEV-41252: partial join cost Assertion failure in recompute_join_cost_with_limit()

recompute_join_cost_with_limit() computes the cost of the first table's
partial join as best_read*fraction - pos->read_time*fraction. When the
two costs are nearly equal and large (e.g. with a huge
optimizer_scan_setup_cost, or when fraction is close to 1), the two
products are rounded independently. The difference can then be a small
negative number whose magnitude exceeds the absolute DBL_EPSILON
tolerance used by the debug assertion, even though it is only a
floating-point rounding artifact.

Fix: scale the assertion tolerance with the magnitude of the operands
(DBL_EPSILON * pos->read_time * fraction). Negative values are still
clamped to 0.0 as before.

Add test cases to optimizer_crash.test, one with a very large
optimizer_scan_setup_cost and optimizer_join_limit_pref_ratio=1, and one
with a large LIMIT on a 30000-row table.
drrtuy
MDEV-40957 replication from InnoDB into DuckDB works using FULL mode only.
drrtuy
MDEV-40957 DuckDB engine now returns maximum cost for unimplemented index handler operations effectively disabling them.
Sergei Petrunia
Add dbug_get_mem_root_alloc_size() debug helper
drrtuy
MDEV-40957 read-free DML on the slave for DuckDB.
Khaled Riyad
MDEV-40377 Change Server source code to point to new docs (11.4 part)

Replace the remaining Knowledge Base links with their MariaDB
Documentation equivalents, including the 838 URLs in the help tables.
Only URLs change in fill_help_tables.sql.

Merging upward: fill_help_tables.sql conflicts at 10.11->11.4 and
11.8->12.3. At those two merges keep the target branch's version,
since 11.4, 11.8 and 12.3 each carry their own URL fix. From 12.3 to
13.1 and 13.1 to main it merges cleanly; take the incoming change.
.github/pull_request_template.md is deleted in 12.3; keep the deletion.
Aleksey Midenkov
MDEV-25529 Comments

* get_next_time() comment
Marko Mäkelä
fixup! 33b746888e75892654df7ffa3a696512656a631d
Alessandro Vetere
MDEV-39792 InnoDB: ALTER TABLE FORCE triggers assertion "s" in buf_page_get_gen()

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

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

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

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

The MDEV-31025 case in innodb.default_row_format_alter failed on
innodb_page_size=4k and 8k: its ROW_FORMAT=REDUNDANT table has eight
utf32 CHAR(255) columns, which CREATE TABLE rejects with
ER_TOO_BIG_ROWSIZE on those page sizes. Derive the number of columns
from the page size, so that the record still exceeds the maximum local
record size and the fixed-length column c is stored externally. The
whole test now passes on every page size.
ParadoxV5
MDEV-38849 slave_connections_needed_for_purge prevents independent machine from purging binary logs

`@@slave_connections_needed_for_purge`’s default of `1` ensures binary
log availability on replication masters, but is not a sensible default
suitable for all scenarios, especially for long-term slave servers and
standalone (not in a replication setup) servers.
The outcome was that standalone server users were confused why automatic
binlog purging does not work.

This commit changes this default to `0`, which is suitable for both
standalone and (when backed by prompt failure recovery)
replication setups.
`0` also more closely matches the behaviour before MDEV-31404,
which added this variable, out of the box.

This commit also adds a one-time replication warning when registering a
slave, but `@@slave_connections_needed_for_purge` is left unchanged.
Rather than enforcing a defence with an unsensible default, this
reminder will bring awareness of the risk of automatic binlog purging.

This commit also cleans up Galera and MTR workarounds to the
introduction of the `@@slave_connections_needed_for_purge=1` default.
drrtuy
MDEV-40957 mixed-mode replication UPDATE/DELETE for DuckDB.
drrtuy
MDEV-40957 various fixes for mixed DML path that suffered from uninit bitmaps and wrong SQL statements that failed in DuckDB.
Aleksey Midenkov
MDEV-25529 ALTER TABLE FORCE syntax improved

Improves ALTER TABLE syntax when alter_list can be supplied alongside a
partitioning expression, so that they can appear in any order. This is
particularly useful for the FORCE clause when adding it to an existing
command.

Also improves handling of AUTO with FORCE, so that AUTO FORCE
specified together provides more consistent syntax, which is used by
this task in further commits.
Sergei Golubchik
MDEV-41431 LOAD_FILE checks for is_secure_file_path() one path but opens another
Yuchen Pei
MDEV-41064 Use my_safe_alloca for unescaped json server option string

This fixes segv when the option string is longer than thread stack