Console View
|
Categories: connectors experimental galera main |
|
| connectors | experimental | galera | main | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thirunarayanan Balathandayuthapani
thiru@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41282 Recursion in InnoDB FTS AST causes stack-overflow (fts_ast_free_node/fts_ast_free_list) Problem: ======= fts_ast_free_node() and fts_ast_free_list() called each other, so releasing the parse tree consumed one pair of thread stack frames for every level of the tree. sub_expr: '(' expr_lst ')' creates one FTS_AST_SUBEXP_LIST per pair of parentheses, so a boolean mode query with 2000 nested parentheses builds a chain of 4002 nodes, and fts_query_free() overflowed the thread stack while freeing it. fts_ast_visit() does not reach that depth, because fts_ast_visit_sub_exp() limits the sub-expression nesting to 32 levels and returns DB_OUT_OF_MEMORY. The parser has built the whole tree by then, and it still has to be freed. fts_ast_node_print_recursive() recurses the same way. It is called from fts_query_parse() when innodb_ft_enable_diag_print is enabled, so it overflows the stack right after parsing, before the query is executed. Solution: ======== fts_ast_free_node(): Free the sub-tree with an explicit stack instead of by recursion. The stack is threaded through the next pointer of the very nodes that are about to be freed, so it needs no extra memory and cannot fail to allocate. A node is only pushed once it has been detached from the tree. The children of a list are already chained to each other by next, so a whole list is spliced onto the stack in one step. fts_ast_free_list(): Removed, no longer needed. fts_ast_node_print_recursive(): Stop at FTS_AST_PRINT_MAX_LEVEL and print "..." instead of descending further. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thirunarayanan Balathandayuthapani
thiru@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41281 Unbounded Recursion in InnoDB FTS Boolean-Mode causes Stack-Overflow fts_ast_visit expr_lst: expr_lst sub_expr wrapped the expression list parsed so far in a newly created FTS_AST_LIST for every sub-expression, so a query such as '(word)' repeated N times built N nested lists. fts_ast_visit() recurses once per FTS_AST_LIST and overflowed the thread stack; the default thread_stack was exhausted at about 2300 repetitions. Append the sub-expression to the list that is already being built, and create a list only when there is none yet, the way the neighbouring expr_lst: expr_lst expr rule has always done. The sub-expressions now become siblings of a single list and the depth no longer grows. This also corrects '+term (subexpr)'. The FTS_EXIST pass used to run to completion in the inner list before the sub-expression was unioned at the outer level, so rows that matched only the sub-expression were returned. Based on mysql/mysql-server@e46e9db484a051db6ffb0abd2b06d3b38ef71a35 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch '10.11' into 10.11-MDEV-40878 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Kristian Nielsen
knielsen@knielsen-hq.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41562: Old slave with semi-sync and binlog-in-engine master With binlog-in-engine, semi-sync replication is supported only when the slave (and the master) is at least MariaDB 13.2. So make sure to give an error if an old slave connects to a master with binlog-in-engine enabled and the slave has semi-sync enabled. Signed-off-by: Kristian Nielsen <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41844 Test innodb.buf_pool_resize_pcur_restore is flaky The procedure read_into_first_new_block() requires that the page of a table is read into the first block that a buffer pool grow adds. While history exists, the purge coordinator runs once per second. It reads undo log pages, and purge_truncation_callback() reads the header page of each rollback segment. On a slow builder, these reads can take the first new block in all 5 attempts. Stop purge for the duration of the test with FLUSH TABLES ... FOR EXPORT on a separate connection. A read view does not stop these reads. Remove the wait for purge between the two cases, because purge is stopped. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41632 UPPER(key_col) IN (constant subquery) returns incorrect row 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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
bsrikanth-mariadb
srikanth.bondalapati@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41749: FederatedX pushdown sends "<nop>(" in pushed-down SQL A pushed-down statement containing "x < SOME (subquery)" failed on the remote server with a syntax error, as the query text contained the internal "<nop>(...)" wrapper. "x < ALL (subquery)" is wrapped in "<not>(...)" in the same way. Item_func_not_all::print() prints the wrapper whenever `show` is set. Omit it when QT_PARSABLE is requested and print the wrapped predicate in parentheses, as precedence() reports the wrapper, so a parent expression would not add parentheses itself. While the ALL/ANY subquery item is intact, args[0] prints the original "x op ALL|ANY (subquery)". When the subquery is reduced to a constant ("x < ALL (SELECT 2)"), it is replaced by a comparison with the inverted comparator, and the negation is held by "<not>". Print it explicitly as "NOT (x >= 2)" for ALL, otherwise the remote server returns the complementary rows. ANY/SOME needs no negation. Item_allany_subselect::print() printed its left operand without parentheses, so "(a XOR b) < ALL (subquery)" was pushed as "a xor b < all (...)" and parsed by the remote server as "a XOR (b < ALL ...)". Use print_parenthesised(), as Item_in_subselect::print() does. Add tests to federatedx_pushdown_upd_del covering SOME and ALL in UPDATE, DELETE and SELECT, with results compared with pushdown OFF and the pushed-down text checked in the remote general log. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Marko Mäkelä
marko.makela@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41506: Broken recovery of SET GLOBAL innodb_log_archive=OFF on PMEM recv_sys_t::find_checkpoint(): When modifying log_sys.archive, remember to call mtr_t::finisher_update(). mtr_t::finisher_validate(): A validation predicate for srv_start(). Reviewed by: Thirunarayanan Balathandayuthapani |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fix main.grant_repair on Windows when user.MAI ends with Ctrl-Z The test patches user.MAI from perl, opened in text mode. On Windows that strips a trailing 0x1A byte on close, so the index file becomes one byte shorter and the server reports a size mismatch instead of repairing the table. Open the file with the :raw layer. Assisted-by: Claude:claude-sonnet-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Jan Lindström
jan.lindstrom@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Record test result after protocol change. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fix SSL test failures with GnuTLS client (11.4) With WITH_SSL=bundled the server uses wolfSSL and Connector/C is built with GnuTLS. The GnuTLS backend reports a CA-signed server certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN, which neither --ssl-fp nor password-based verification can override (OpenSSL reports it as MARIADB_TLS_VERIFY_TRUST). The fix: main.ssl_fp skip unless the client uses OpenSSL or LibreSSL main.mysql pass --ssl-ca to a GnuTLS client for the --ssl-verify-server-cert check rpl.rpl_semi_sync_no_missed_ack_after_add_slave include default_client.cnf, so check-testcase connects with --disable-ssl-verify-server-cert (also done in 10.11) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fix SSL test failures with GnuTLS client (10.11) The test .cnf does not include default_client.cnf, so clients do not get loose-disable-ssl-verify-server-cert. Since 11.4 the client verifies the server certificate by default. With WITH_SSL=bundled Connector/C is built with GnuTLS, which reports the CA-signed test server certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN, so check-testcase fails to connect to server 2 with "The certificate issuer is unknown". The fix includes default_client.cnf into the test .cnf, like other rpl tests do. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
sjaakola
seppo.jaakola@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-38981 Galera loses wsrep_gtid_domain_id after pc.recovery restart Fix for MDEV-24546 changed the storage for wsrep_gtid_domain_id (either in config file or as an option) to be into wsrep_gtid_domain_id variable. And it is copied to wsrep_gtid_server struct's domain_id only in the variable's ON_UPDATE hookw. On server startup this struct was set only by the bootstrap (startup with --wsrep-new-cluster) or by SST/IST donation from the donor. When all nodes crashed and the cluster re-formed through pc.recovery, neither of these happened, so wsrep_init_gtid() replaced the recovered domain with 0. New writes then got domain 0. And afer this, later joiners also inherited domain 0 from their donor. The fix here is simply to copy wsrep_gtid_domain_id to wsrep_gtid_server struct in wsrep_init_server(), before any state transfer. Commit has a new mtr test: galera.MDEV-38981, Assisted-by: https://mariadb.org/governance/governance-ai-policy/ |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Marko Mäkelä
marko.makela@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41506: Broken recovery of SET GLOBAL innodb_log_archive=OFF on PMEM recv_sys_t::find_checkpoint(): When modifying log_sys.archive, remember to call mtr_t::finisher_update(). mtr_t::finisher_validate(): A validation predicate for srv_start(). Reviewed by: Thirunarayanan Balathandayuthapani |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fixup be807b2d047: match GnuTLS only, not every non-OpenSSL client Schannel on Windows is not OpenSSL either, but handles these cases. Assisted-by: Claude:claude-sonnet-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41251 Wrong result with split materialized query A query like SELECT * FROM t0 WHERE t0.b IN (SELECT t.n2 FROM t1, (SELECT n1, n2 FROM t1 GROUP BY n1, n2) t WHERE t.n1 = t1.n1 AND t1.c1 = 'a' UNION SELECT -1) returned only the row of t0 that was read first, when the derived table t was split-materialized. The IN->EXISTS transformation wraps t0.b in an Item_cache owned by the Item_in_optimizer, and injects t.n2 = <cache>(t0.b) into the subquery. The optimizer then pushes an equality on n2 into the derived table, so that the table only has to be filled with the matching rows. TABLE::add_splitting_info_for_key_field() built the right side of that equality as a deep copy of <cache>(t0.b). A copy of a cache is a second cache: it read t0.b for the first row of t0 and kept that value, because only the Item_in_optimizer stores new values, and it stores them into the original cache. Every later refill of the derived table was filtered on the first row's value. The right side is an expression of the outer select used inside the select that specifies the derived table. Add a copy hierarchy for that purpose. Item::new_select_copy_with_checks(thd, item_select) returns a copy for use in a select nested in item_select, the select the item belongs to. In the nested select the copy is an outer reference to item_select: - An Item_field is copied and its depended_from set to item_select. This is what add_splitting_info_for_key_field() did before with set_fields_as_dependent_processor, except that depended_from now names the select the column belongs to instead of the nested select. - An Item_direct_view_ref, a column of a merged view or derived table, is also copied like a column: the copy refers to a new_select_copy() of the item the view column stands for. Copying it this way, as the deep copy did, keeps a column of a constant NULL-complemented table constant in the pushed equality (the MDEV-30081 test in main.derived_cond_pushdown still shows ref "const" for its LATERAL DERIVED table). - Any other item that depends on tables of item_select is not copied. The copy is an Item_direct_ref to the original item, with depended_from set to item_select. So the nested select reads the cache, aggregate or subquery that its owner keeps up to date, instead of a copy of it that nobody refreshes. Item_default_value is treated this way too. - An item that depends on no table of item_select is shared. The copy is fixed, and only refers to tables outside the select it is used in, which the wrapper asserts. add_splitting_info_for_key_field() now uses it for the right side of the pushed equality, and no longer walks the copy with set_fields_as_dependent_processor or calls update_used_tables() on it. The debug-only copy of key_field->val used for the lookup still uses deep_copy_with_checks(). The check_deep_copy() call on the right side is removed, as it is no longer meant to be a deep copy. A second test, taken from Dave Gosselin's MDEV-41251 commit, pushes a comparison, dt.a <=> (t1.b = 1), and its row form. The deep copy of the comparison was never fixed again. Its Arg_comparator still pointed at the original, which sets null_value of the original, and a copied row comparison had comparators set to NULL. The row of t1 with a NULL b was missing from the result, and the row form crashed in Arg_comparator::compare_row(). Now the comparison is not copied: the right side refers to the original. This commit was prepared with Claude Code (Opus 5), which designed and wrote the new_select_copy() hierarchy, switched the split equality to it, wrote the three-row test from the earlier rr analysis, added the comparison test, confirmed in a build of the parent commit that both tests fail without the change, and ran main and the SQL-layer suites in normal and --ps-protocol mode. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40878 avoid repeated parsing of PROXY headers Do not parse multiple proxy headers. The protocol spec says the header is at the beginning of a connection, so there could only be one. According to example in the spec, in multi-layer scenarios, where several proxies are involved between client and backend, the intermediate proxy is supposed to be configured to replace the existing header. Thus multiple headers are not expected. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fix SSL test failures with GnuTLS client With WITH_SSL=bundled the server uses wolfSSL and Connector/C is built with GnuTLS. The GnuTLS backend reports a CA-signed server certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN, which neither --ssl-fp nor password-based verification can override (OpenSSL reports it as MARIADB_TLS_VERIFY_TRUST). The fix: main.ssl_fp skip unless the client uses OpenSSL or LibreSSL main.mysql pass --ssl-ca to a GnuTLS client for the --ssl-verify-server-cert check rpl.rpl_semi_sync_no_missed_ack_after_add_slave include default_client.cnf, so check-testcase connects with --disable-ssl-verify-server-cert (also done in 10.11) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41746: IN-subquery not allowed with OFFSET Prevent OFFSET from appearing in IN, ALL, or ANY subqueries with error ER_NOT_SUPPORTED_YET. This mirrors how we prevent LIMIT from appearing in similar queries. Previously, OFFSET queries within IN-subqueries could return wrong results if for example the OFFSET was past the end of the table. Also print OFFSET n ROWS when there is no FETCH clause. Before, view definitions and EXPLAIN EXTENDED omitted such an OFFSET. Views and derived tables with such an OFFSET are no longer merged into the outer query because merging discarded the OFFSET. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fix main.grant_repair on Windows when user.MAI ends with Ctrl-Z The test patches user.MAI from perl, opened in text mode. On Windows that strips a trailing 0x1A byte on close, so the index file becomes one byte shorter and the server reports a size mismatch instead of repairing the table. Open the file with the :raw layer. Assisted-by: Claude:claude-sonnet-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41746: IN subquery accepted with OFFSET clause An IN, ALL, or ANY subquery with OFFSET but no LIMIT was accepted and the OFFSET was ignored, producing wrong results. The same subquery with LIMIT is rejected with ER_NOT_SUPPORTED_YET. st_select_lex::test_limit() now also rejects a subquery that has an OFFSET, with the message 'OFFSET & IN/ALL/ANY/SOME subquery'. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thirunarayanan Balathandayuthapani
thiru@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41281 Unbounded Recursion in InnoDB FTS Boolean-Mode causes Stack-Overflow fts_ast_visit expr_lst: expr_lst sub_expr wrapped the expression list parsed so far in a newly created FTS_AST_LIST for every sub-expression, so a query such as '(word)' repeated N times built N nested lists. fts_ast_visit() recurses once per FTS_AST_LIST and overflowed the thread stack; the default thread_stack was exhausted at about 2300 repetitions. Append the sub-expression to the list that is already being built, and create a list only when there is none yet, the way the neighbouring expr_lst: expr_lst expr rule has always done. The sub-expressions now become siblings of a single list and the depth no longer grows. This also corrects '+term (subexpr)'. The FTS_EXIST pass used to run to completion in the inner list before the sub-expression was unioned at the outer level, so rows that matched only the sub-expression were returned. Based on mysql/mysql-server@e46e9db484a051db6ffb0abd2b06d3b38ef71a35 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thirunarayanan Balathandayuthapani
thiru@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41282 Recursion in InnoDB FTS AST causes stack-overflow (fts_ast_free_node/fts_ast_free_list) Problem: ======= fts_ast_free_node() and fts_ast_free_list() called each other, so releasing the parse tree consumed one pair of thread stack frames for every level of the tree. sub_expr: '(' expr_lst ')' creates one FTS_AST_SUBEXP_LIST per pair of parentheses, so a boolean mode query with 2000 nested parentheses builds a chain of 4002 nodes, and fts_query_free() overflowed the thread stack while freeing it. fts_ast_visit() does not reach that depth, because fts_ast_visit_sub_exp() limits the sub-expression nesting to 32 levels and returns DB_OUT_OF_MEMORY. The parser has built the whole tree by then, and it still has to be freed. fts_ast_node_print_recursive() recurses the same way. It is called from fts_query_parse() when innodb_ft_enable_diag_print is enabled, so it overflows the stack right after parsing, before the query is executed. Solution: ======== fts_ast_free_node(): Free the sub-tree with an explicit stack instead of by recursion. The stack is threaded through the next pointer of the very nodes that are about to be freed, so it needs no extra memory and cannot fail to allocate. A node is only pushed once it has been detached from the tree. The children of a list are already chained to each other by next, so a whole list is spliced onto the stack in one step. fts_ast_free_list(): Removed, no longer needed. fts_ast_node_print_recursive(): Stop at FTS_AST_PRINT_MAX_LEVEL and print "..." instead of descending further. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40878 avoid repeated parsing of PROXY headers Do not parse multiple proxy headers. The protocol spec says the header is at the beginning of a connection, so there could only be one. According to example in the spec, in multi-layer scenarios, where several proxies are involved between client and backend, the intermediate proxy is supposed to be configured to replace the existing header. Thus multiple headers are not expected. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Khaled Riyad
khaled57.dev@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41140 mariadb-server.postinst chown dereferences symlinks The postinst, preinst, rpm postin and mysqld_safe scripts followed symlinks when fixing ownership and permissions under /var/log/mysql and /var/lib/mysql. Use -h and find -execdir, drop the rpm chmod, and let mysqld_safe write as the mysql user, so symlinks there are no longer dereferenced. Behavior changes. - symlinks inside these directories are no longer followed - only the top level of /var/log/mysql is adjusted, not subdirectories - the rpm scriptlet no longer runs chmod on the permission database |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-40878 avoid repeated parsing of PROXY headers Do not parse multiple proxy headers. The protocol spec says the header is at the beginning of a connection, so there could only be one. According to example in the spec, in multi-layer scenarios, where several proxies are involved between client and backend, the intermediate proxy is supposed to be configured to replace the existing header. Thus multiple headers are not expected. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Add cmake option RUN_UNSTABLE_TESTS for unit tests Add the RUN_UNSTABLE_TESTS CMake option (default OFF) to exclude flaky or timing-sensitive tests from default builds and CI runs. Mark test_tls_openssl_err2 as unstable because it frequently times out on GitHub Actions. Manual verification confirmed that OpenSSL correctly returns x509_error=2 for the certificate provided by the fake server. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41746: IN-subquery not allowed with OFFSET Prevent OFFSET from appearing in IN, ALL, or ANY subqueries with error ER_NOT_SUPPORTED_YET. This mirrors how we prevent LIMIT from appearing in similar queries. Previously, OFFSET queries within IN-subqueries could return wrong results if for example the OFFSET was past the end of the table. Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39566 crash on a sorted scan of performance_schema.status_by_* The bitmap of materialized rows in PFS_table_context was sized by the live row count of the buffer container, which grows while a scan runs: a sorted scan sizes it twice and asserted when the two sizes differed, and set_item() could write past its end. status_by_account used the thread local key of status_by_host. The allocation used the number of bits in a word as its size in bytes. m_last_item started at 0, so set_item(0) did nothing and rnd_pos() dropped the first row. Size the bitmap by the container maximum, which is fixed at startup; give status_by_account its own key THR_PFS_SBA; allocate sizeof(ulong) per word; start m_last_item at a sentinel. Co-Authored-By: Claude Opus 5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39566 crash on a sorted scan of performance_schema.status_by_* The bitmap of materialized rows in PFS_table_context was sized by the live row count of the buffer container, which grows while a scan runs: a sorted scan sizes it twice and asserted when the two sizes differed, and set_item() could write past its end. status_by_account used the thread local key of status_by_host. The allocation used the number of bits in a word as its size in bytes. m_last_item started at 0, so set_item(0) did nothing and rnd_pos() dropped the first row. Size the bitmap by the container maximum, which is fixed at startup; give status_by_account its own key THR_PFS_SBA; allocate sizeof(ulong) per word; start m_last_item at a sentinel. Co-Authored-By: Claude Opus 5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fix SSL test failures with GnuTLS client (11.4) With WITH_SSL=bundled the server uses wolfSSL and Connector/C is built with GnuTLS. The GnuTLS backend reports a CA-signed server certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN, which neither --ssl-fp nor password-based verification can override (OpenSSL reports it as MARIADB_TLS_VERIFY_TRUST). The fix: main.ssl_fp skip unless the client uses OpenSSL or LibreSSL main.mysql pass --ssl-ca to a GnuTLS client for the --ssl-verify-server-cert check rpl.rpl_semi_sync_no_missed_ack_after_add_slave include default_client.cnf, so check-testcase connects with --disable-ssl-verify-server-cert (also done in 10.11) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41844 Test innodb.buf_pool_resize_pcur_restore is flaky The procedure read_into_first_new_block() requires that the page of a table is read into the first block that a buffer pool grow adds. While history exists, the purge coordinator runs once per second. It reads undo log pages, and purge_truncation_callback() reads the header page of each rollback segment. On a slow builder, these reads can take the first new block in all 5 attempts. Stop purge for the duration of the test with FLUSH TABLES ... FOR EXPORT on a separate connection. A read view does not stop these reads. Remove the wait for purge between the two cases, because purge is stopped. purge_sys_t::stop() waits only for the purge coordinator. Runs of purge_truncation_callback() that the coordinator submitted before can still read pages after FLUSH TABLES ... FOR EXPORT returns. Add the debug keyword purge_stop_wait_truncation, which makes purge_sys_t::stop() also wait for these runs, and set it in the test. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge 10.11 into 10.11-MDEV-40878 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-35867 mariadb-check --repair does not repair sequences, only changes the status to OK REPAIR of a sequence table with more or fewer than one row reported OK. Now ha_sequence::repair() checks the row count after the engine repair and reports the sequence as corrupt. Also a failed table recreate in REPAIR was reported as "Table is already up to date" (bool result taken as HA_ADMIN_ALREADY_DONE). Co-Authored-By: Claude Opus 5.5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thirunarayanan Balathandayuthapani
thiru@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41282 Recursion in InnoDB FTS AST causes stack-overflow (fts_ast_free_node/fts_ast_free_list) Problem: ======= fts_ast_free_node() and fts_ast_free_list() called each other, so releasing the parse tree consumed one pair of thread stack frames for every level of the tree. sub_expr: '(' expr_lst ')' creates one FTS_AST_SUBEXP_LIST per pair of parentheses, so a boolean mode query with 2000 nested parentheses builds a chain of 4002 nodes, and fts_query_free() overflowed the thread stack while freeing it. fts_ast_visit() does not reach that depth, because fts_ast_visit_sub_exp() limits the sub-expression nesting to 32 levels and returns DB_OUT_OF_MEMORY. The parser has built the whole tree by then, and it still has to be freed. Solution: ======== fts_ast_free_node(): Free the sub-tree with an explicit stack instead of by recursion. The stack is threaded through the next pointer of the very nodes that are about to be freed, so it needs no extra memory and cannot fail to allocate. A node is only pushed once it has been detached from the tree. The children of a list are already chained to each other by next, so a whole list is spliced onto the stack in one step. fts_ast_free_list(): Removed, no longer needed. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Khaled Riyad
khaled57.dev@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41140 mariadb-server.postinst chown dereferences symlinks The postinst, preinst, rpm postin and mysqld_safe scripts followed symlinks when fixing ownership and permissions under /var/log/mysql and /var/lib/mysql. Use -h and find -execdir, drop the rpm chmod, and let mysqld_safe write as the mysql user, so symlinks there are no longer dereferenced. Behavior changes. - symlinks inside these directories are no longer followed - only the top level of /var/log/mysql is adjusted, not subdirectories - the rpm scriptlet no longer runs chmod on the permission database |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
forkfun
alice.sherepa@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-29510 ASAN errors upon updating a BLOB column twice in one UPDATE UPDATE t SET a='x', b=a, a='foobarqux' makes b alias a's value buffer (field_conv_memcpy() copies only the blob pointer while copy_blobs is off). Storing a again frees that buffer and b dangles. So does INSERT ... ON DUPLICATE KEY UPDATE. fill_record(update=true) now stores a blob by value, unless the source is a same-type blob column in engine memory, which nothing frees. With copy_blobs set, Field_blob::store_field() copies a same-type blob verbatim, skipping the charset check, and stores anything else through store(), which checks the length. A trigger or UPDATE storing a longer blob into a shorter one now fails or truncates with a warning, instead of storing a wrapped length. ODKU: VALUES() reads blob pointers saved in insert_values, which point into Field_blob::value. Keep those buffers aside until the update is done, so storing into a column does not overwrite them. With BEFORE triggers, NOT NULL columns are stored through the field_to_fill() clones, so keep those buffers too. Assisted-by: Claude:claude-5.5-sonnet |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fixup be807b2d047: match GnuTLS only, not every non-OpenSSL client Schannel on Windows is not OpenSSL either, but handles these cases. Assisted-by: Claude:claude-sonnet-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Fix SSL test failures with GnuTLS client (11.4) With WITH_SSL=bundled the server uses wolfSSL and Connector/C is built with GnuTLS. The GnuTLS backend reports a CA-signed server certificate with an unknown issuer as MARIADB_TLS_VERIFY_UNKNOWN, which neither --ssl-fp nor password-based verification can override (OpenSSL reports it as MARIADB_TLS_VERIFY_TRUST). The fix: main.ssl_fp skip unless the client uses OpenSSL or LibreSSL main.mysql pass --ssl-ca to a GnuTLS client for the --ssl-verify-server-cert check rpl.rpl_semi_sync_no_missed_ack_after_add_slave include default_client.cnf, so check-testcase connects with --disable-ssl-verify-server-cert (also done in 10.11) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||