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
Sergei Golubchik
fix RPAD(), LPAD() and INSERT() not to mangle its arguments

they used to overwrite the charset of their arguments, this is
incorrect and led to wrong results
Rex Johnston
MDEV-41228 Add Item::pushdown_copy() for condition pushdown

Condition pushdown into materialized derived tables and views, into
materialized IN subqueries, and from HAVING into WHERE copies parts of a
condition with deep_copy_with_checks(). These copies are all made for the
same purpose. The pushdown code transforms the copy, replacing the columns
it refers to with what the target select computes them from, then walks
it with cleanup_excluding_const_fields_processor and fixes it again in the
target select.

That walk cleans up every node it reaches, and Item_field::cleanup() drops
the field. So none of these copies may share a node with the original,
including the copies of select list items that the transformers insert:
those would be cleaned up under the select list. This rules out
same_select_copy() for the transformers, although their copies stay in the
same select, and needs a copy hierarchy of its own.

Item::pushdown_copy_with_checks() calls the protected virtual
Item::pushdown_copy(). It copies every node, and does not use deep_copy()
at any level. A failure to copy is a valid answer: the condition is then
not pushed down.

- The default, in Item, copies the node with shallow_copy().
- Item_func_or_sum, Item_ref, Item_cond, Item_row, Item_default_value,
  Item_direct_ref_to_item and Item_assoc_array copy their child items too.
  Item_func_or_sum copies its arguments before creating its own copy, so
  that an argument that cannot be copied leaves no half-made copy behind,
  whose cleanup() would free what it still shares with the original.
- Item_cache copies its example, unless that is or contains an aggregate or
  window function, which cannot be copied. The copy then shares the example
  with the original cache. The cleanup walk never reaches it, because every
  transformer the pushdown code applies before the walk replaces an
  Item_cache with a basic constant, or fails and the condition is not
  pushed. main.derived_cond_pushdown (MDEV-10882) copies such a cache.
- Item_bool_rowready_func2, Item_func_case_simple and Item_func_in give
  the copy its own comparators and value array.
- Item_outer_ref and Item_cache_fbt are copied as a single node.
- The classes that deep_copy() refuses to copy refuse here too: subqueries,
  parameters, SP variables that are not plain values, MATCH, the spatial
  relations, Item_cache_row, Item_cache_wrapper, Item_type_holder and the
  PROCEDURE items.

The copies made by Item::build_pushable_cond(),
Item_equal::create_pushable_equalities(), pushdown_cond_for_derived(),
st_select_lex::build_cond_for_grouping_fields() and the
derived_field, grouping_field and in_subq_field transformers for WHERE now
use pushdown_copy_with_checks().

This commit was prepared with Claude Code (Opus 5), which found that the
pushdown cleanup walk rules out shared nodes in these copies, wrote the
pushdown_copy() hierarchy from the deep_copy() overrides, switched the
pushdown call sites to it, found and fixed the half-made copy crash that
main.derived_cond_pushdown (MDEV-17177) showed in its first version,
checked with tracing that the
pushdown cleanup walk never reaches the aggregate that a copy of an
Item_cache shares, and ran main and the SQL-layer suites in normal and
--ps-protocol mode.
Marko Mäkelä
Push posix_fadvise() deeper, and copy up to 16MiB at a time.
Monty
Remove C++ STL machinery from sql/rpl_*info_file.* and CHANGE MASTER parser

Replaces std::function / std::optional / std::unordered_map /
std::unordered_set / std::string_view and template-heavy code in the
master.info / relay-log.info persistence layer with plain MariaDB
idioms.
- On-disk file format unchanged.
- SQL syntrax unchanged
- No notable test changes, except those for which new error messages was
  added and output from SHOW VARIABLES.
- master_* CLI options moved from inline globals in
  rpl_master_info_file.h to Sys_var_* in sys_vars.cc (READ_ONLY,
  AUTO_SET on use_gtid and heartbeat_period). master_heartbeat_period
  is Sys_var_double (seconds); master_use_gtid is Sys_var_enum. Global
  storage sits outside HAVE_REPLICATION so libmariadbd links.
  - This adds the rpl_master_info variables to SHOW VARIABLES
- Value classes are no longer templates. Persistent renamed to Value;
  Optional_* classes renamed (Uint_value_with_default, Path_value,
  etc.).  has_value flag in the base; is_default()
  non-virtual. Multi-line method bodies moved to new rpl_info_file.cc
  and rpl_master_info_file.cc.
- VALUE_LIST (Mem_fn array) and VALUE_MAP (std::unordered_map)
  replaced by per-instance Value *const value_list[] / value_map[]
  arrays + a static TYPELIB populated at first construction from each
  Value's variable_name. seen-set dedup is now a uint32 bitmask.
- Default handling is not anymore done with using special values.
  Setting a value to default is now done by calling set_default(),
  which sets the has_value member to 0 and stores the default value
  in the variable.
  When reading a value, one does not have to check if the value is
  a default value.
  This makes the interface cleaner and easier to manage.
- CHANGE MASTER TO parser no longer builds std::function lambdas:
  LEX_MASTER_INFO carries mi_used_options / mi_used_default bitmasks
  plus plain value fields; change_master() applies them via bit-test +
  direct copy or set_default(). std::optional<T> and trilean are gone
  from the value class API.
- Heartbeat_period_value::load_from uses my_strtod() instead of
  my_decimal for the on-disk format. from_decimal kept for CHANGE
  MASTER.
- RocksDB #if __cplusplus < 201703L guard at the top of
  rpl_master_info_file.h dropped; header now compiles in C++11.
  cstdint dropped; uint32_t / UINT32_MAX in touched code replaced by
  MariaDB's uint32 / UINT_MAX32. include/my_global.h gains
  INT_BUFFER_SIZE next to LONGLONG_BUFFER_SIZE.
- Pointer-style throughout (T * not T &). Multi-line inline functions
  used in more than one place moved to .cc files per style.

New features:
- SHOW VARIABLES now shows the master default values.
- If there is an wrong value for a row in a master.info file the
  corresponding variable name and the value is now written to the
  error log.

Bug fixes uncovered by the refactor:
- master_ssl_verify_server_cert had a pre-existing inconsistency with
  security implications: the documented default and the Sys_var_mybool
  default are TRUE (validate the master's certificate), but the OLD
  init_ssl_config() set the per-Master_info field to FALSE on RESET
  SLAVE ALL. Concretely: after RESET SLAVE ALL followed by a bare
  CHANGE MASTER TO (no explicit MASTER_SSL_VERIFY_SERVER_CERT), the
  slave would connect with MASTER_SSL=1 enabled but with certificate
  validation silently disabled.
  Fixed by not resetting master_ssl_verify_server_cert in
  RESET SLAVE ALL;
- As some replication setups sets master_ssl_verify_server_cert= 0
  while other does not do that, the expected value used in
  check-testcase.inc "Master_SSL_Verify_Server_Cert No" does not make
  sense.  The value of this variable is now ignored by
  check-testcase.inc
- The old code would fail to read a master info file if there was a new
  variable longer than 23 characters. This is now extended to 80.
- Removed warning on RESET SLAVE that "RESET SLAVE is implicitly changing"
  the value of 'Using_Gtid' from 'No' to 'Slave_Pos'" as this change did
  not really happen. This error was given if the master could support
  GTID but the user had specified directly or indirectly to not use GTID.

Other things
- Size of mariadb (optimize build) shrunk with 1,408,009 bytes
  (Based on 'dec' from the size command)
- Size of code in sql directory did not change notable.
- Reworked Master_use_gtid_value to remember users last choice and use
  this as default when connecting to slave.
  Replace mi->using_gtid, with was a pointer to master_use_gtid, with
  two functions:
  - using_gtid() returns the current mode, for the code that needs the
    value itself (SHOW SLAVE STATUS and performance schema output,
    comparisons against CURRENT_POS and SLAVE_POS).
  - is_gtid_supported() tells whether the connection uses gtid at all.
    The many callers that compared the mode against USE_GTID_NO with
    == or != now call this function instead of testing the enum value.
- Master_use_gtid_value::supported() did the same test as
  is_gtid_supported() and is removed
- Removed some operators in rpl_master_info_file.* that hid
  that functions was used to read and update values.

Behavior changes:
- The last used value in CHANGE MASTER for MASTER_USE_GTID will be
  remembered for future CHANGE MASTER for the same connection. This is
  true even if RESET SLAVE is called.
- If Using git is not used with change master but log_file_name, pos,
  relay_log_name or relay_log_pos is specified this is treated as
  if Using_git=NO would have been given. (Old behavior, but not
  documented).
--auto-master-use-gtid does nothing. The default value of
  master_use_gtid is by default SlavePos that will automatically
  change to NO if the master does not support GTID. This already
  handles what auto-master-use-gtid tries to do.
- CHANGE MASTER's MASTER_HEARTBEAT_PERIOD now works like other MASTER
  options:  When set to a value, this value is kept until value is
  changed or set to DEFAULT. The DEFAULT is
  @global.master_heartbeat_period if this is set as startup, if not
  then @global.slave_net_timeout/2 is used.
Rex Johnston
MDEV-41228 Read the row of Item_func_interval through args[0]

A query like

  select * from (select a, b from t1 group by a, b) d
    where interval(d.a, 3, 7) = 1

returned no rows when the condition was pushed into the derived table,
although the row (5,20) matches, as condition_pushdown_for_derived=off
shows.

Item_func_interval kept its first argument, the Item_row, in a member
of its own as well as in args[0]. Condition pushdown copies the condition
with deep_copy(). The copy of the node got new arguments but kept the
member, so it went on reading the original row: the INTERVAL() pushed into
the derived table compared the original outer column, and the pushed
condition rejected every row.

Item_func_interval now reads the row through args[0] alone, so a copy
cannot point anywhere else.

This commit was prepared with Claude Code (Opus 5), which found the stale
member, made Item_func_interval read the row through args[0], wrote the
test and confirmed in a build of the parent commit that it fails without
the change, and ran main and the SQL-layer suites in normal and
--ps-protocol mode on the series that contains it.
Monty
Have mtr also use /usr/lib64/libgalera_smm.so when searching for wsrep lib
Dave Gosselin
MDEV-41146:  Merge pseudo_bits_cond into outer_ref_cond

A join of only const tables stored the WHERE conjuncts that refer to a
column of an outer query or call rand() in pseudo_bits_cond.  The
executor read pseudo_bits_cond only when the query needed no temporary
table, and read outer_ref_cond otherwise.  A window function or
DISTINCT with ROLLUP needs a temporary table, so those conjuncts were
never checked, and the query returned rows that the WHERE clause
rejects.

pseudo_bits_cond came from the fix for LP bug 908269 in 2012.  For a
join of only const tables, that fix also collected conjuncts that call
rand(), and it stored them in a new field without stating a reason.
The code that filled the two fields and the code that read them chose
between them by the same test.  The tests have differed since
MDEV-8646 in 2016, which added the temporary table condition to the
executor's test.  Later changes only display the field, in EXPLAIN
FORMAT=JSON (MDEV-19714) and in the optimizer trace (MDEV-21095).  In
MDEV-19714, its author wrote that it was not clear why pseudo_bits_cond
was needed in addition to outer_ref_cond.

pseudo_bits_cond is removed, and outer_ref_cond holds these conjuncts
for every join.  The executor checks it on both paths, so where the
conjuncts are stored no longer depends on the executor's test.
Conjuncts that call rand() are still collected only for a join of only
const tables.  EXPLAIN FORMAT=JSON shows these conjuncts as
outer_ref_condition instead of pseudo_bits_condition.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Sergei Golubchik
cleanup: use StringBuffer<>
Sergei Golubchik
ER_OUT_OF_SORTMEMORY should not be ME_ERROR_LOG+ME_FATAL

it's not OOM, it's "filesort requires more memory than a user specified
session local limit". Not a hardware limitation, but something
an unprivileged user configured in her own session (so, shouldn't
be ME_ERROR_LOG). And unlike true low-memory situation this error
condition doesn't affect following statements (so, shouldn't be ME_FATAL)
ParadoxV5
MDEV-32947 Async conflicts with semi-sync in multi-source

`@@rpl_semi_sync_slave_enabled` can be changed without stopping
replication, because it takes effect when a connection is established.
But when it takes effect, it applies to *all* replication connections.
This means that starting an async connection will switch any ongoing
semi-sync connections to async as well, and vice versa, which will
cause those connections to fail to replicate in the wrong mode.

This fix resolves this oversight by changing the value application
to be specific to only the establishing connection (technically,
moving the singleton’s field `Repl_semi_sync_slave::m_slave_enabled`
to the instance variable `Master_info::semi_sync_enabled`).
This design builds toward MDEV-40941, which proposes migrating
`@@rpl_semi_sync_slave_enabled` to a proper per-connection config.
Note, `Master_info::semi_sync_reply_enabled` must remain separate,
because it only disables ACK replying in async slave fallback,
whereas the semi-sync slave setting also controls whether the IO
thread should expect additional semi-sync flags in event packets.

To maintain backward compatibility until MDEV-40941,
the status variable `Rpl_semi_sync_slave_status` is kept showing
the applied `@@rpl_semi_sync_slave_enabled` for the most recent
START SLAVE in any connection; that is, not yet made per-connection.

Reviewed-by: Brandon Nesterenko <[email protected]>
Monty
Avoid strlen() calls in Explain_index_usage and String_list

Use Lex_ident_column* instead of char* as parameters
Oleg Smirnov
Pushdown from HAVING: Fail the query on errors

The pushdown from HAVING into WHERE modifies HAVING before all of its
steps have succeeded. On a failure it emptied the list of pushed
conditions and let the query continue, so the conditions already
removed from HAVING were not checked at all.

pushdown_from_having_into_where() now returns an error status, and
the query errors out if the pushdown fails after it may have modified
HAVING. thd->lex->current_select is now restored on all return paths.
It was not restored when collecting the grouping fields failed.
forkfun
MDEV-30295 mysqldump produces syntactically incorrect statement

cover_definer_clause() wrapped DEFINER in "*/ /*!50017 ... */" and broke
when the statement text contained a comment. Dump the server's DDL
as returned.

Also:
- drop /*!NNNNN */ gates below 50700 in mysqldump, mysqlbinlog,
  mysqladmin, mysqlcheck, mysqlshow, mysqlimport, mysqlhotcopy,
  innotop and mtr_warnings.sql; mysqlbinlog's skip_replication
  becomes /*M! ...*/
- SHOW CREATE DATABASE no longer wraps IF NOT EXISTS and DEFAULT
  CHARACTER SET in comments
- remove checks for servers older than 5.7 in mysqldump, mysqlcheck,
  mysql, innotop and the client library, including dump_trigger_old()
  and mysqlcheck's SHOW TABLES fallback
- mysqldump warns on stderr if SHOW CREATE DATABASE fails

Behavior changes:
- --compatible=mysql323 and mysql40 are accepted and ignored. The other
  modes wrap only some SET and ALTER TABLE ... KEYS statements in
  /*!40101 */.
- mysqlhotcopy --old_server is accepted, ignored, and prints a warning.

Assisted-By: Claude:claude-5.5-sonnet
Sergei Golubchik
MDEV-41540 filesort assert crash on a huge sort key

sort key could go over 4GB making sort length to wrap around.
let's limit sort key length by 2GB - still ridiculously unrealistically
large but far enough from 4GB so that any additions in the code below
would still be safe.

The error is somewhat confusing, but, again, only someone who pushes
the margins to exploit memory bugs will ever see it.

Additionally min_sort_memory calculations are done as uint and
can wrap around too, allocating later over 4GB memory not constrained
by @@sort_buffer_size
Sergei Golubchik
cleanup: connect test
Rex Johnston
MDEV-41228 Remove Item::deep_copy()

Every copy of an item tree that the server makes now goes through a copy
hierarchy named after its purpose: same_select_copy(), new_select_copy()
or pushdown_copy(). deep_copy() was left with three callers:

- Virtual_column_info::clone(), which has had no callers since
  ef5adf52076 (MDEV-24274),
- the "item_cache_clones" debug hook in Item::get_cache(), and
- the "split_materialized_clones" debug hook in
  TABLE::add_splitting_info_for_key_field(), which used a deep copy of
  key_field->val for the lookup into the split-materialized table.

The debug hooks were added only to exercise deep_copy() on Item_cache
items, together with Item::check_deep_copy(), which compared a deep copy
with its original.

Remove all of them, with deep_copy_with_checks(), the pure virtual
deep_copy() and its overrides, Item_cache::deep_copy_cache() and
check_deep_copy(). Item::get_cache() is inline again, as it was before the
debug hook. main.item_clone_debug ran its query under the
split_materialized_clones flag and is removed; the same query, with three
rows in t0 so that a stale value shows in the result, is in
main.derived_split_innodb.

Comments that pointed at deep_copy_with_checks() now point at the copy
functions that replace it.

This commit was prepared with Claude Code (Opus 5), which removed the
deep_copy() hierarchy, its debug hooks, check_deep_copy() and
Virtual_column_info::clone(), restored the inline Item::get_cache(),
removed main.item_clone_debug, and ran main and the SQL-layer suites in
normal and --ps-protocol mode.
Rex Johnston
MDEV-41228 Add Item::new_select_copy() for split materialization

A query like

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

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

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

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

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

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

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

This commit was prepared with Claude Code (Opus 5), which designed and
wrote the new_select_copy() hierarchy, switched the split equality to it,
wrote the three-row test from the earlier rr analysis, added the
comparison test, confirmed in a build of the parent commit that both tests
fail without the change, and ran main and the SQL-layer suites in normal
and --ps-protocol mode.
Sergei Golubchik
cleanup: remove unused variable
Sergei Golubchik
MDEV-41496 OOB write with RPAD() crash and multi-byte charsets and uservar

item's charset is metadata, it's known at fix_fields and does not
change later. user variables can violate this invariant if they're
changed and used in the same query.

Let's always wrap such variables in Item_func_conv_charset()
to make sure the caller always gets the same fixed charset, no matter
what the actual variable value is.

Variables that aren't changed in the same query do not get this
unnecessary conversion.
forkfun
MDEV-30295 mysqldump produces syntactically incorrect statement

cover_definer_clause() wrapped DEFINER in "*/ /*!50017 ... */" and broke
when the statement text contained a comment. Dump the server's DDL
as returned.

Also:
- drop /*!NNNNN */ gates below 50700 in mysqldump, mysqlbinlog,
  mysqladmin, mysqlcheck, mysqlshow, mysqlimport, mysqlhotcopy,
  innotop and mtr_warnings.sql; mysqlbinlog's skip_replication
  becomes /*M! ...*/
- SHOW CREATE DATABASE no longer wraps IF NOT EXISTS and DEFAULT
  CHARACTER SET in comments
- remove checks for servers older than 5.7 in mysqldump, mysqlcheck,
  mysql, innotop and the client library, including dump_trigger_old()
  and mysqlcheck's SHOW TABLES fallback
- mysqldump warns on stderr if SHOW CREATE DATABASE fails

Behavior changes:
- --compatible=mysql323 and mysql40 are accepted and ignored. The other
  modes wrap only some SET and ALTER TABLE ... KEYS statements in
  /*!40101 */. DEFINER, DROP ... IF EXISTS, CREATE VIEW/TRIGGER/EVENT
  and FLUSH PRIVILEGES are no longer wrapped, so scripts matching
  /*!50017 DEFINER=... */ stop matching.

Assisted-By: Claude:claude-5.5-sonnet
Monty
Add likely/unlikely to my_b_read/write functions
Monty
Remove wrong assert in log_event_server.cc

The test for:
DBUG_ASSERT(thd->lex->query_tables != table_list);
does not make any sense:
- table_list is a pointer we just got from malloc)()
- thd->lex->query_tables can point to an existing TABLE_LIST
  or is a pointer to already freed memory.

In 'main' I got the above assert multiple times triggered when
running rpl.rpl_row_img_blobs on a valgrind build. There was
nothing wrong with the allocations, just random change have
malloc return a recently freed pointer.
Sergei Golubchik
Item_func_decode_histogram::val_str shouldn't modify its arguments
ParadoxV5
MDEV-32947 Async conflicts with semi-sync in multi-source

`@@rpl_semi_sync_slave_enabled` can be changed without stopping
replication, because it takes effect when a connection is established.
But when it takes effect, it applies to *all* replication connections.
This means that starting an async connection will switch any ongoing
semi-sync connections to async as well, and vice versa, which will
cause those connections to fail to replicate in the wrong mode.

This fix resolves this oversight by changing the value application
to be specific to only the establishing connection (technically,
moving the singleton’s field `Repl_semi_sync_slave::m_slave_enabled`
to the instance variable `Master_info::semi_sync_enabled`).
This design builds toward MDEV-40941, which proposes migrating
`@@rpl_semi_sync_slave_enabled` to a proper per-connection config.
Note, `Master_info::semi_sync_reply_enabled` must remain separate,
because it only disables ACK replying in async slave fallback,
whereas the semi-sync slave setting also controls whether the IO
thread should expect additional semi-sync flags in event packets.

To maintain backward compatibility until MDEV-40941,
the status variable `Rpl_semi_sync_slave_status` is kept showing
the applied `@@rpl_semi_sync_slave_enabled` for the most recent
START SLAVE in any connection; that is, not yet made per-connection.

Reviewed-by: Brandon Nesterenko <[email protected]>
Dave Gosselin
MDEV-39173:  Use snprintf in the remaining sprintf calls

Convert all three calls to snprintf.  12.3 already has the same change
for slave.cc, made in merge commit 9f98f82b14a.

MDEV-39173 replaced sprintf with snprintf in 10.11 and removed the
pragma in violite.h that hid deprecation warnings.  Two calls in
slave.cc and one in mysqltest.cc were added after 10.11, so 11.4 was
out of date and produces sprintf deprecation warnings (at least on
macOS).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Rex Johnston
MDEV-41228 Add Item::same_select_copy() for the casefold rewrite

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. 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.

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.

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 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. That item is always a column, so the copy is the column itself,
where the deep copy made a second Item_field for it. The equality is fixed
when it is injected. The split_materialized_clones check of the left side
is removed, as it is no longer meant to be a deep copy.

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.
Dmitry Shulga
MDEV-30645: CREATE TRIGGER FOR { STARTUP | SHUTDOWN }

Core implementation

- Extended the sql grammar to support creation of system triggers
  on startup/shutdown
- System triggers metadata is stored in the table mysql.event
- Events and system triggers share the same name space since both are stored
  in the table mysql.event declared with the PRIMARY KEY (`db`,`name`).
  In result, attempt to create an event with the same name as existent
  trigger and vice versa results in failure with the new error
  ER_TRG_EVENT_CONFLICTS_NAME
- Since system triggers metadata is stored in the mysql.event table,
  on handling the DROP TRIGGER statement the table mysql.event now is opened
- System triggers can be created only by users with the SUPER privilege
- Added the option --sys_triggers for mysqldump to dump system triggers.
  The option is turned off by default. In case this option is on, mysqldump
  first dump the table 'mysql' unconditionally, regardless whether
  it was listed in the option --ignore-database
Monty
Remove warnings from aria_chk

- Added right path to datadir where aria_log_control is
- Added option --ignore-control-file as the server is keeping it locked.
Sergei Golubchik
MDEV-41608 some CONNECT jfile/bfile udfs ignore FILE and secure_file_priv

also they should all have maybe_null=true
Monty
Fixed wrong code in ha_perfschema::delete_table()

In case there was no '/' or '\' in the path, *ptr = '\0' would
change data outside of table_path[]

This patch also removes a warning from gcc.
Rex Johnston
MDEV-41228 Check the class of the copy made by Item::shallow_copy()

Item::shallow_copy() was meant to create a copy of the same class as the
item it is called on, but nothing enforced that. A class that does not
declare its own override inherits the one of its nearest concrete parent,
and get_item_copy<Parent>() then silently creates an object of the parent
class, losing the child's virtual behaviour (see MDEV-38801 for an earlier
instance with Item_cache_year).

Add the ITEM_SHALLOW_COPY(CLASS) macro, which declares the override, and
Item::dbug_check_shallow_copy_type(), a debug-only check called from
Query_arena::free_items() for every item freed. Once per dynamic type it
creates a shallow copy, unlinks it from thd->free_list again (the copy shares
pointers with the original and must not be destroyed) and asserts that the
copy has the same typeid as the original. The copy is never destroyed: its
destructor is not run, and its memory is released when the MEM_ROOT it was
allocated on, the current thd->mem_root, is freed. A comment in the check
says so.

The check found these classes copied as their parent class, now fixed with
ITEM_SHALLOW_COPY():
  Item_join_operator_plus, Item_null_result, Item_old_field, Item_datetime,
  Item_empty_string, Item_return_int, Item_trigger_type_of_statement,
  in_string::Item_string_for_in_vector, Item_is_not_null_test,
  Item_interval_DDhhmmssff_typecast, Item_string_xml_non_const,
  Item_func_trt_trx_sees_eq, Item_field_refcursor (type_cursor plugin),
  Item_field_packable_scalar (type_assoc_array plugin).

Item_field_packable_row::shallow_copy() asserted to mark the class as never
copied, which the check trips over since it copies every type it meets. It
now returns nullptr, the existing way for an item to refuse a copy.

No test is added: the check runs under every existing test in a debug build.
main and the SQL-layer suites (compat/*, json, funcs_*, vcol, gcol,
versioning, period, sys_vars, type_*) pass with it in both normal and
--ps-protocol mode.

This commit was prepared with Claude Code (Opus 5), which wrote the runtime
type check, ran the main and SQL-layer suites in normal and --ps-protocol
mode to find the classes that inherited a parent's copy method, added the
ITEM_SHALLOW_COPY overrides for them, changed Item_field_packable_row to
return nullptr, and documented where the copy made by the check is
released.
Dave Gosselin
MDEV-41146:  Merge pseudo_bits_cond into outer_ref_cond

A join of only const tables stored the WHERE conjuncts that refer to a
column of an outer query or call rand() in pseudo_bits_cond.  The
executor read pseudo_bits_cond only when the query needed no temporary
table, and read outer_ref_cond otherwise.  A window function or
DISTINCT with ROLLUP needs a temporary table, so those conjuncts were
never checked, and the query returned rows that the WHERE clause
rejects.

pseudo_bits_cond came from the fix for LP bug 908269 in 2012.  For a
join of only const tables, that fix also collected conjuncts that call
rand(), and it stored them in a new field without stating a reason.
The code that filled the two fields and the code that read them chose
between them by the same test.  The tests have differed since
MDEV-8646 in 2016, which added the temporary table condition to the
executor's test.  Later changes only display the field, in EXPLAIN
FORMAT=JSON (MDEV-19714) and in the optimizer trace (MDEV-21095).  In
MDEV-19714, its author wrote that it was not clear why pseudo_bits_cond
was needed in addition to outer_ref_cond.

pseudo_bits_cond is removed, and outer_ref_cond holds these conjuncts
for every join.  The executor checks it on both paths, so where the
conjuncts are stored no longer depends on the executor's test.
Conjuncts that call rand() are still collected only for a join of only
const tables.  EXPLAIN FORMAT=JSON shows these conjuncts as
outer_ref_condition instead of pseudo_bits_condition.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Sergei Golubchik
MDEV-41603 DECODE_HISTOGRAM crashes when decoding JSON_HB

don't return a pointer to a local buffer
Monty
Fixed bug in rpl.rpl_killed_ddl.result test case

View 'v1' was not always dropped (timeing issue)
Val Doroshchuk
MDEV-40845: DuckDB: reject SELECT ... FOR UPDATE / LOCK IN SHARE MODE

DuckDB has no row locks and its parser rejects locking clauses, so
SELECT ... FOR UPDATE on a DuckDB table failed with ER_GET_ERRMSG
("Parser Error: SELECT locking clause is not supported!") coming from
the embedded DuckDB.

Check for locking reads in ha_duckdb::external_lock() and raise
ER_NOT_SUPPORTED_YET from the storage engine instead. The check only
applies to SQLCOM_SELECT, so INSERT ... SELECT, UPDATE and DELETE are
not affected.
Dave Gosselin
MDEV-41146:  Check rand() in WHERE when top level base tables are const

A WHERE conjunct that calls rand() but doesn't refer to a column, such
as rand() < 0, is checked on the last non-const top level base table
in the join order.  A join of only const tables has no such table and
returns at most one row, so the conjunct is checked once before the
join starts, together with the conditions on columns of an outer
query.

When every top level base table is const and materialized semi-joins
follow them, the join order also has no non-const top level base
table, but only_const_tables() is false.  The conjunct was never
checked, and such a query gave wrong results.

The check before the join now applies whenever the join order has no
non-const top level base table, which is the same condition under
which no table in the join order receives the conjunct.  Such a join
also returns at most one row.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Sergei Golubchik
fix RPAD(), LPAD() and INSERT() not to mangle its arguments

they used to overwrite the charset of their arguments, this is
incorrect and led to wrong results
forkfun
MDEV-30295 mysqldump produces syntactically incorrect statement

cover_definer_clause() wrapped DEFINER in "*/ /*!50017 ... */" and broke
when the statement text contained a comment. Dump the server's DDL
as returned.

Also:
- drop /*!NNNNN */ gates below 50700 in mysqldump, mysqlbinlog,
  mysqladmin, mysqlcheck, mysqlshow, mysqlimport, mysqlhotcopy and
  innotop; mysqlbinlog's skip_replication becomes /*M! ...*/
- SHOW CREATE DATABASE no longer wraps IF NOT EXISTS and DEFAULT
  CHARACTER SET in comments
- remove old-server checks: dump_trigger_old(), mysqlcheck's SHOW TABLES
  fallback
- mysqldump warns on stderr if SHOW CREATE DATABASE fails

Behavior changes:
- --compatible=mysql323 and mysql40 are accepted and ignored. The other
  modes wrap only some SET and ALTER TABLE ... KEYS statements in
  /*!40101 */. DEFINER, DROP ... IF EXISTS, CREATE VIEW/TRIGGER/EVENT
  and FLUSH PRIVILEGES are no longer wrapped, so scripts matching
  /*!50017 DEFINER=... */ stop matching.

Assisted-By: Claude:claude-5.5-sonnet
Sergei Golubchik
MDEV-41496 OOB write with RPAD() crash and multi-byte charsets and uservar

item's charset is metadata, it's known at fix_fields and does not
change later. user variables can violate this invariant if it's
changed and used in the same query.

Let's always wrap such variables in Item_func_conv_charset()
to make sure the caller always gets the same fixed charset, no matter
what the actual variable value is.

Variables that aren't changed in the same query do not get this
unnecessary conversion.
Dave Gosselin
MDEV-41146:  Check rand() in WHERE when top level base tables are const

A WHERE conjunct that calls rand() but doesn't refer to a column, such
as rand() < 0, is checked on the last non-const top level base table
in the join order.  A join of only const tables has no such table and
returns at most one row, so the conjunct is checked once before the
join starts, together with the conditions on columns of an outer
query.

When every top level base table is const and materialized semi-joins
follow them, the join order also has no non-const top level base
table, but only_const_tables() is false.  The conjunct was never
checked, and such a query gave wrong results.

The check before the join now applies whenever the join order has no
non-const top level base table, which is the same condition under
which no table in the join order receives the conjunct.  Such a join
also returns at most one row.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>