Console View
|
Categories: connectors experimental galera main |
|
| connectors | experimental | galera | main | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 ALTER TABLE FORCE syntax improved Lets an alter_list be supplied alongside a partitioning or remove_partitioning clause in either order. This allows the FORCE clause to be added to an existing command, and lets AUTO and FORCE be specified together, which later commits of this task rely on. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 Comment on partition_element allocation in set_up_default_partitions() partition_element and its push_back() list node are allocated on the active arena (thd->mem_root). The allocation failure is already reported there (by my_malloc() or the arena's error handler), which is why the failure path only returns the error. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 ErrConvTimestamp for printing timestamps Add ErrConvTimestamp, an ErrConv that formats a Timestamp in the session time zone into a fixed buffer for warning and error messages, with the number of fractional digits given explicitly. ErrBuff::set_mysql_time() gets an optional digits argument for it. 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
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 Auto-create: Pre-existing historical data is not partitioned as specified by ALTER Adds logic into prep_alter_part_table() for INTERVAL ... AUTO to read the history range (vers_get_history_range()) and size the new layout from it. STARTS is aligned to the oldest history row_end (vers_set_starts()) if it was not specified by the user, or if the user specified it later than that; in the latter case WARN_VERS_WRONG_STARTS is printed. The history partitions cover both the newest history row_end and the query time, so DML after the ALTER does not need to create partitions. A PARTITIONS N clause is kept if it gives more partitions. An explicit subpartition list is replaced by as many default subpartitions. If the layout needs more than MAX_PARTITIONS partitions (counting subpartitions), or the INTERVAL is longer than the date range, the ALTER fails with ER_VERS_HIST_PART_FAILED. Month and year intervals are stepped in UTC; a boundary past the maximum TIMESTAMP ends a partial last history partition. 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. With FORCE on a table already partitioned by SYSTEM_TIME the work is done on a clone of the partitioning info. The parsed settings are copied into the clone's vers_info with Vers_part_info::copy_settings(), which keeps the clone's now_part and hist_part (the parsed ones are NULL). Before reading the range, the metadata lock is upgraded to MDL_SHARED_NO_WRITE, and then the copy does not run online, so DML cannot add history that would not fit the computed layout until the ALTER ends (Alter_info::vers_history_read). LOCK=NONE and ALGORITHM=INPLACE/NOCOPY/INSTANT are rejected for such ALTER before the upgrade, so they do not wait for concurrent DML; the ALGORITHM error is reported by the new Alter_info::report_algorithm_unsupported(), which mysql_alter_table() uses as well. The range is read under a table lock taken with mysql_lock_tables(), as some engines (Aria) set up their transaction in THR_LOCK callbacks. The scan can be killed. WARN_VERS_STARTS_BEYOND_INTERVAL for ALTER .. AUTO is checked after the alignment, so it is not printed when STARTS was re-aligned to the history. vers_get_history_range() detects if an 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 a table scan to read the stats. Current rows with the pre-11.5 row_end marker are not taken for history either. In the index they sort below history after 2038, so the minimum is read after them. There is test_mdev-25529 debug keyword to check the both and compare results. WARN_VERS_SLOW_ROW_END is printed if the scan read any row and there is no usable index (a disabled one does not count as missing). 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
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41543 Changing INTERVAL of SYSTEM_TIME partitioning does not move history ALTER TABLE ... PARTITION BY SYSTEM_TIME with a changed INTERVAL or STARTS on a table already partitioned by SYSTEM_TIME took the fast ALTER path, which only rewrites the table definition. The history rows stayed where the old layout put them, so after the ALTER they were in wrong partitions. An unchanged interval took the copy path instead. MDEV-29873 replaced memcmp() of the intervals, which is true when they differ, with interval_t::operator==, which is true when they are equal, and lost the negation. The copy path was also broken: it assigned the whole vers_info of the new partitioning spec to the cloned partition info, now_part and hist_part included. The ALTER does not list partitions, so now_part became NULL and check_partition_info() failed with ER_VERS_WRONG_PARTS for a table with explicit partitions (MDEV-33370 test case). The fix negates the comparison again (now with interval_t::operator!=), so a changed interval rebuilds the table and redistributes the history. It copies only interval, limit and auto_hist from the new spec and keeps now_part and hist_part of the existing partitions. Without STARTS the start of the interval defaults to the current time rounded down to the INTERVAL unit. So ALTER with the same INTERVAL and no STARTS usually gets a different start and now rebuilds the table. Vers_part_info::operator=, which copied now_part and hist_part and had no other callers, is deleted. Fast ALTER was also chosen when the same statement changed the table definition, e.g. ADD COLUMN with the same INTERVAL and STARTS, or DROP COLUMN with LIMIT. It wrote the new .frm, but the partitions kept the old record layout. Now any change of the table definition (alter_info->flags) takes the copy path. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41543 Changing INTERVAL of SYSTEM_TIME partitioning does not move history ALTER TABLE ... PARTITION BY SYSTEM_TIME with a changed INTERVAL or STARTS on a table already partitioned by SYSTEM_TIME took the fast ALTER path, which only rewrites the table definition. The history rows stayed where the old layout put them, so after the ALTER they were in wrong partitions. An unchanged interval took the copy path instead. MDEV-29873 replaced memcmp() of the intervals, which is true when they differ, with interval_t::operator==, which is true when they are equal, and lost the negation. The copy path was also broken: it assigned the whole vers_info of the new partitioning spec to the cloned partition info, now_part and hist_part included. The ALTER does not list partitions, so now_part became NULL and check_partition_info() failed with ER_VERS_WRONG_PARTS for a table with explicit partitions (MDEV-33370 test case). The fix negates the comparison again (now with interval_t::operator!=), so a changed interval rebuilds the table and redistributes the history. It copies only interval, limit and auto_hist from the new spec and keeps now_part and hist_part of the existing partitions. Without STARTS the start of the interval defaults to the current time rounded down to the INTERVAL unit. So ALTER with the same INTERVAL and no STARTS usually gets a different start and now rebuilds the table. Vers_part_info::operator=, which copied now_part and hist_part and had no other callers, is deleted. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-35845 Let string constants enter multiple equalities for all collations SELECT * FROM t1 WHERE v IN ('a','b') AND v = 'b' kept both conjuncts when v is a utf8mb4 column, while the same query on a latin1 column was simplified to v = 'b'. BETWEEN and the constant in a join equality (t1.v = t2.v AND t1.v = 'b') were left alone in the same way. The rewrite is done by the multiple equality machinery, not by propagate_cond_constants(). check_simple_equality() turns v = 'b' into an Item_equal holding the column and the constant. Later substitute_for_best_equal_field() walks the remaining predicates, and Item_func_in::propagate_equal_fields() asks each argument that is a column of an Item_equal to replace itself with that constant whenever the predicate compares under the Item_equal's collation. 'b' IN ('a','b') is then constant and remove_eq_conds() folds it away. The same path serves BETWEEN, <=> and every other comparison, and eliminate_item_equal() derives t2.v = 'b' from the join equality. A constant was only admitted into an Item_equal when the column's collation handler reported propagate() true. That flag was added in 2005 for Bug#9509, when a constant taken from an Item_equal was substituted into any expression, so LENGTH(s1) saw 'oe' instead of the o-umlaut it equals under latin1_german2_ci. Every utf8mb3 and utf8mb4 case-insensitive collation and every UCA collation report false, so once MDEV-19123 made utf8mb4 the default, no string column got a constant in its Item_equal. Since MDEV-7152 the substitution is decided per site by a Context: comparison operators accept the constant only when their comparison collation is the Item_equal's, everything else only for binary no-pad collations, and LIKE refuses pad and non-1-to-1 collations on its own. The flag therefore duplicated a finer check, and propagate_cond_constants() had been substituting the same constants into = and < under the same collations without consulting it. Field_str::test_if_equality_guarantees_uniqueness() no longer consults it either; the remaining tests, that the constant compares as a string and under the column's own collation, stay. That exposes one case the flag was hiding. Charset narrowing (cset_narrowing) lets a utf8mb3_general_ci column and a utf8mb4_general_ci column share an Item_equal, so the Item_equal now also has to hold a utf8mb4 constant for its utf8mb3 member. eliminate_item_equal() manufactures utf8mb3_col = utf8mb4_const for that member, which fails collation aggregation when the constant has a character outside the BMP. Field_longstr::get_equal_const_item() converts the constant from the Item_equal's comparison collation into the member's character set, through the mb4-to-mb3 narrowing charset when narrowing applies, so that a character outside the BMP becomes U+FFFD, which is what utf8mb4_general_ci compares it as. It returns NULL, and the equality is dropped, when the constant cannot be represented. eliminate_item_equal() calls it for every member it builds an equality for; Item_field::propagate_equal_fields() already did. The tests added to func_in.test come from Dave Gosselin's patch for this issue, which handled IN in propagate_cond_constants() instead. Two of its expectations change with this approach: an Item_equal prints its constant first, and v IN ('a',NULL) AND v = 'b' now folds to an impossible WHERE, as 'b' IN ('a',NULL) is NULL. The other re-recorded results show the same reordering, or improved plans where a constant now reaches another table. This commit was prepared with Claude Code (Fable 5.1), which traced the missing rewrite to the propagate() check, showed by experiment that removing it restores the rewrite and passes the func_in tests, found the narrowing failure from a query supplied by the author, wrote Field_longstr::get_equal_const_item() and its call in eliminate_item_equal(), re-recorded the affected results, and ran the main suite in normal and --ps-protocol mode before and after. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41542: Wrong results, crash when upgrading to OpenSSL 4.x Allocates the OpenSSL cipher context of MyCTX with EVP_CIPHER_CTX_new() and frees it with EVP_CIPHER_CTX_free(), instead of using a buffer in MyCTX that was zeroed and then passed to EVP_CIPHER_CTX_reset(). With OpenSSL 4.x, the statement SELECT HEX(AES_ENCRYPT('foo', 'bar', '0123456789abcdef', 'aes-256-cbc')); returns NULL instead of 42A3EB91E6DFC40A900D278F99E0726E, failing the main.func_str test. EVP_CIPHER_CTX_new() sets the IV length of a new context to -1. OpenSSL 3.6.5 EVP_CIPHER_CTX_reset() sets it to -1, but OpenSSL 4.0.3 EVP_CIPHER_CTX_reset() leaves a context with no cipher unchanged. EVP_CipherInit_ex() then fails with an invalid IV length. my_aes_crypt_init() returns MY_AES_OPENSSL_ERROR when the allocation fails. It also destroys the context when init fails, because callers do not call my_aes_crypt_finish() after a failed init. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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. When every top level base table was const and the join order ended with materialized semi-joins, the conjunct was never checked. Such a query gave wrong results. In that scenario the join returns at most one row, so the conjunct is now checked once before the join starts, together with the conditions on columns of an outer query. The decision uses the same search for the last top level base table that places the conjunct in every other case. A join of only const tables has no such table, and the same test covers it. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41540 filesort assert crash on a huge sort key sortlength cannot be larger than 4G. If it's reaching the limit, stop growing the sort key, ignore the tail same as for max_sort_length. test allocates ~4GB of memory even if very briefly and even if it doesn't actually use it. So only run it on 64bit, on 32bit let it fails with "Out of sort memory" - but still no crash. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| get_next_time() comment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Monty
monty@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Brandon Nesterenko
brandon.nesterenko@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
squash! 6e3fd9cbbca55c18f29a62850d0add915dbc71b5 Replace the Master_info::using_gtid pointer with accessor functions. Master_info kept a pointer into Master_use_gtid_value::active_mode and all readers accessed the current gtid mode through using_gtid[0]. The pointer member added an indirection on every check and hid where the value actually lives. Master_info_file now provides two inline functions instead, both going directly to the member: * 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; its only caller now uses the new function. The conversion of the call sites is mechanical and there is no change in behavior. Co-Authored-By: Claude Fable 5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41542: Wrong results, crash when upgrading to OpenSSL 4.x Removes EVP_CIPHER_CTX_SIZE, the EVP_CIPHER_CTX_init() macro of ssl_compat.h and the part of check_openssl_compatibility() that measures EVP_CIPHER_CTX_new(). MyCTX was their only user, and it now allocates its context with EVP_CIPHER_CTX_new() so these are otherwise unused. Consequently, mysqld no longer refuses to start when an OpenSSL cipher context is larger than 200 bytes. The EVP_MD_CTX check is unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 ErrConvTimestamp for printing timestamps Add ErrConvTimestamp, an ErrConv that formats a Timestamp in the session time zone into a fixed buffer for warning and error messages, with the number of fractional digits given explicitly. ErrBuff::set_mysql_time() gets an optional digits argument for it. 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
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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, Datetime and Date, which shared the identical flaw, so all five report OOM consistently. The val_str() implementations that return the to_string() result directly did not set null_value, so a NULL result would be taken for a value. They now go through the new Item::check_str(), which sets null_value from the result, so a NULL does not stick to the item for the next execution. The time_to_string_oom debug keyword makes Time::to_string() fail as on out of memory. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 Auto-create: Pre-existing historical data is not partitioned as specified by ALTER Adds logic into prep_alter_part_table() for INTERVAL ... AUTO to read the history range (vers_get_history_range()) and size the new layout from it. STARTS is aligned to the oldest history row_end (vers_set_starts()) if it was not specified by the user, or if the user specified it later than that; in the latter case WARN_VERS_WRONG_STARTS is printed. The history partitions cover both the newest history row_end and the query time, so DML after the ALTER does not need to create partitions. A PARTITIONS N clause is kept if it gives more partitions. An explicit subpartition list is replaced by as many default subpartitions. If the layout needs more than MAX_PARTITIONS partitions (counting subpartitions), or the INTERVAL is longer than the date range, the ALTER fails with ER_VERS_HIST_PART_FAILED. Month and year intervals are stepped in UTC; a boundary past the maximum TIMESTAMP ends a partial last history partition. 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. With FORCE on a table already partitioned by SYSTEM_TIME the work is done on a clone of the partitioning info. The parsed settings are copied into the clone's vers_info with Vers_part_info::copy_settings(), which keeps the clone's now_part and hist_part (the parsed ones are NULL). Before reading the range, the metadata lock is upgraded to MDL_SHARED_NO_WRITE, and then the copy does not run online, so DML cannot add history that would not fit the computed layout until the ALTER ends (Alter_info::vers_history_read). LOCK=NONE and ALGORITHM=INPLACE/NOCOPY/INSTANT are rejected for such ALTER before the upgrade, so they do not wait for concurrent DML; the ALGORITHM error is reported by the new Alter_info::report_algorithm_unsupported(), which mysql_alter_table() uses as well. The range is read under a table lock taken with mysql_lock_tables(), as some engines (Aria) set up their transaction in THR_LOCK callbacks. The scan can be killed. WARN_VERS_STARTS_BEYOND_INTERVAL for ALTER .. AUTO is checked after the alignment, so it is not printed when STARTS was re-aligned to the history. vers_get_history_range() detects if an 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 a table scan to read the stats. Current rows with the pre-11.5 row_end marker are not taken for history either. In the index they sort below history after 2038, so the minimum is read after them. There is test_mdev-25529 debug keyword to check the both and compare results. WARN_VERS_SLOW_ROW_END is printed if the scan read any row and there is no usable index (a disabled one does not count as missing). 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
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 Comment on partition_element allocation in set_up_default_partitions() partition_element and its push_back() list node are allocated on the active arena (thd->mem_root). The allocation failure is already reported there (by my_malloc() or the arena's error handler), which is why the failure path only returns the error. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41545 Unchecked get_clone() in ALTER of partitioned table crashes on out-of-memory get_clone() returns NULL on out-of-memory, but two of its callers in prep_alter_part_table() dereferenced the result without a check, so the server crashed: changed INTERVAL of SYSTEM_TIME partitioning ADD PARTITION under LOCK TABLES get_clone() itself did not check the allocation of Vers_part_info and dereferenced it. handle_alter_part_error() did not check the clone either. The clone only kept the DDL log entries after the table is closed. In the branch where DDL log recovery fails, write_log_completed() released the entries through lpt->part_info, which the table close may have freed, and release_log_entries() released the same entries again through the clone. That branch is not reachable now, as ddl_log_execute_entry() always returns false. The fix checks the allocation of Vers_part_info in get_clone() and the result of get_clone() in prep_alter_part_table() like the other callers there do. handle_alter_part_error() keeps a copy of DDL_LOG_STATE instead of the clone and passes it to write_log_completed() and release_log_entries(), which now take DDL_LOG_STATE. The redundant release_log_entries() after write_log_completed() is removed. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 Extract vers_set_starts() and add starts_clause Extracts the STARTS-alignment logic into vers_set_starts() so it can be reused. If the aligned local time falls into a DST gap (e.g. a midnight that does not exist), the start of the gap is used instead of failing with ER_PART_WRONG_VALUE. If it falls before the TIMESTAMP range (e.g. a local midnight before 1970), the timestamp itself is used. Also adds the Vers_part_info::starts_clause flag in preparation for later commits. The flag records whether STARTS was given explicitly (by the user or in the unpacked frm), which the auto-partitioning code uses to decide whether to re-align STARTS to the existing history. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Monty
monty@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Add likely/unlikely to my_b_read/write functions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 Replace COMBINE macro with interval2sec() and interval2usec() Turn the COMBINE macro of date_add_interval() into inline functions with overloads for INTERVAL and MYSQL_TIME, so that the history partition sizing can reuse the seconds part. Move the "Daynumber" comment that sat above the macro to MAX_DAY_NUMBER, which it describes. MAX_DAY_NUMBER moves to sql_time.h as a constexpr (the unused copy in item_timefunc.cc is removed), and the range check of date_add_interval() becomes the inline interval_days_out_of_range(), so that the sizing can check that the seconds do not overflow. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-35845 Let string constants enter multiple equalities for all collations SELECT * FROM t1 WHERE v IN ('a','b') AND v = 'b' kept both conjuncts when v is a utf8mb4 column, while the same query on a latin1 column was simplified to v = 'b'. BETWEEN and the constant in a join equality (t1.v = t2.v AND t1.v = 'b') were left alone in the same way. The rewrite is done by the multiple equality machinery, not by propagate_cond_constants(). check_simple_equality() turns v = 'b' into an Item_equal holding the column and the constant. Later substitute_for_best_equal_field() walks the remaining predicates, and Item_func_in::propagate_equal_fields() asks each argument that is a column of an Item_equal to replace itself with that constant whenever the predicate compares under the Item_equal's collation. 'b' IN ('a','b') is then constant and remove_eq_conds() folds it away. The same path serves BETWEEN, <=> and every other comparison, and eliminate_item_equal() derives t2.v = 'b' from the join equality. A constant was only admitted into an Item_equal when the column's collation handler reported propagate() true. That flag was added in 2005 for Bug#9509, when a constant taken from an Item_equal was substituted into any expression, so LENGTH(s1) saw 'oe' instead of the o-umlaut it equals under latin1_german2_ci. Every utf8mb3 and utf8mb4 case-insensitive collation and every UCA collation report false, so once MDEV-19123 made utf8mb4 the default, no string column got a constant in its Item_equal. Since MDEV-7152 the substitution is decided per site by a Context: comparison operators accept the constant only when their comparison collation is the Item_equal's, everything else only for binary no-pad collations, and LIKE refuses pad and non-1-to-1 collations on its own. The flag therefore duplicated a finer check, and propagate_cond_constants() had been substituting the same constants into = and < under the same collations without consulting it. Field_str::test_if_equality_guarantees_uniqueness() no longer consults it either; the remaining tests, that the constant compares as a string and under the column's own collation, stay. That exposes one case the flag was hiding. Charset narrowing (cset_narrowing) lets a utf8mb3_general_ci column and a utf8mb4_general_ci column share an Item_equal, so the Item_equal now also has to hold a utf8mb4 constant for its utf8mb3 member. eliminate_item_equal() manufactures utf8mb3_col = utf8mb4_const for that member, which fails collation aggregation when the constant has a character outside the BMP. Field_longstr::get_equal_const_item() converts the constant from the Item_equal's comparison collation into the member's character set, through the mb4-to-mb3 narrowing charset when narrowing applies, so that a character outside the BMP becomes U+FFFD, which is what utf8mb4_general_ci compares it as. It returns NULL, and the equality is dropped, when the constant cannot be represented. eliminate_item_equal() calls it for every member it builds an equality for; Item_field::propagate_equal_fields() already did. The tests added to func_in.test come from Dave Gosselin's patch for this issue, which handled IN in propagate_cond_constants() instead. Two of its expectations change with this approach: an Item_equal prints its constant first, and v IN ('a',NULL) AND v = 'b' now folds to an impossible WHERE, as 'b' IN ('a',NULL) is NULL. The other re-recorded results show the same reordering, or improved plans where a constant now reaches another table. This commit was prepared with Claude Code (Fable 5.1), which traced the missing rewrite to the propagate() check, showed by experiment that removing it restores the rewrite and passes the func_in tests, found the narrowing failure from a query supplied by the author, wrote Field_longstr::get_equal_const_item() and its call in eliminate_item_equal(), re-recorded the affected results, and ran the main suite in normal and --ps-protocol mode before and after. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41542: Wrong results, crash when upgrading to OpenSSL 4.x OpenSSL 4 reports a TLS alert as "tls alert ..." where OpenSSL 3 reports "ssl/tls alert ..." and OpenSSL 1.1.1 reports "sslv3 alert ...". main.tlsv13 and main.ssl_crl replace the 1.1.1 text with the 3.x text, so they failed when linked against OpenSSL 4. Both now replace the 4.x text as well, and the expected results are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Lawrin Novitsky
lawrin.novitsky@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-16670 Improve execute direct (prepare and execute) performance The patch detects if the processed PREPARE command is first part of the pipelined DIRECT+EXECUTE commands with stmt id -1 for execution. For that the vio class has been extended with peek method that lets us verify that the server has already received next command, it is EXECUTE with stmt id -1, and the packet is minimally complete. If it is so, the execution is forwarded to the fused prepare+execute path as if it was a single command. It lets a statement's execute leg run before any real prepare/check_prepared_statement() has happened and the prepare leg does basically query parsing only. Several places downstream assumed that had already happened, so give Query_arena a single predicate, is_direct_exec_unresolved() - true only for the one-shot fused pass that never went through a real prepare - and fix each broken assumption against it: * Query cache: a cached response is replayed without ever running mysql_execute_command(), so the buffered prepare-response hook never fires; conversely, populating the cache captures that hook's bytes too (net_real_write() sees the whole flushed buffer), poisoning the entry for unrelated later clients. Direct-exec statements now opt out of the query cache entirely (query_cache_is_applicable / lex->safe_to_cache_query, saved and restored around just that one execution). Covered by test_mdev_16670_qc_hit_hang and test_mdev_16670_qc_poison. * Reprepare: a mid-execute reprepare() (e.g. ER_NEED_REPREPARE) swaps in a lex that DID go through a real prepare, so the statement is no longer "unresolved" once that happens - tracked via a new IS_DIRECT_EXEC_REPREPARED flag so the direct-exec special-casing only applies to the original pass. * System versioning / periods: skip_setup_conds() treated the fused pass as an ordinary re-execution rather than a first resolution, so vers_setup_conds()/period_setup_conds() never ran - a versioned table or FOR PORTION OF statement used the wrong predicate. Now counted as "first execute" via is_direct_exec_unresolved(). Covered by test_mdev_16670_versioned_rows and test_mdev_16670_trigger_versioned. * Unsupported statements check used to be done as part of the check_prepared_statement, has been moved to the new check_stmt_command_supported function called from the Prepared_statement::prepare method. Covered by test_mdev_16670_unsupported_ps. * CALL statements and queries referencing a stored function are excluded from the optimized path (skip_direct_exec_optimization()): their nested sub-statements run with thd->cur_stmt still pointing at the outer statement, which would otherwise misfire the buffered prepare-response hook. Also, the stored function use would cause guaranteed re-prepare. The flag is reset for them after the query parsing. Covered by test_mdev_16670_demoted_function_call. Also adds regression tests for the reply-pair on parse error (test_mdev_16670_parse_error_reply_pair), SQLSTATE/errno preservation through the execute-leg fallback (test_mdev_16670_fallback_sqlstate), general_log coverage (test_mdev_16670_general_log), a statement killed mid-fallback (test_mdev_16670_kill_during_fallback), and prebind usage of mariadb_stmt_execute_direct() with real bound parameters (test_mdev_16670_prebind_direct). It's possible to compile with global variable opt_exec_direct that controls if the optimization should be used. Its existence can be switched on using cmake option WITH_DIRECT_EXEC_OPTIMIZE_SWITCH. By default it does not exist, as it is believed to be unneeded in the general case. create_and_prepare_stmt() helper added to perform common statement creation routine, and erase_stmt_safely() helper - for cleaning in create_and_prepare_stmt()'s prepare-failure cleanup, direct_exec_prepare_ok_fallback()'s OOM branch, and mysqld_stmt_direct_execute()'s packet_error branch. Assisted-by: Claude Sonnet 5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41545 Unchecked get_clone() in ALTER of partitioned table crashes on out-of-memory get_clone() returns NULL on out-of-memory, but two of its callers in prep_alter_part_table() dereferenced the result without a check, so the server crashed: changed INTERVAL of SYSTEM_TIME partitioning ADD PARTITION under LOCK TABLES get_clone() itself did not check the allocation of Vers_part_info and dereferenced it. handle_alter_part_error() did not check the clone either. The clone only kept the DDL log entries after the table is closed. In the branch where DDL log recovery fails, write_log_completed() released the entries through lpt->part_info, which the table close may have freed, and release_log_entries() released the same entries again through the clone. That branch is not reachable now, as ddl_log_execute_entry() always returns false. The fix checks the allocation of Vers_part_info in get_clone() and the result of get_clone() in prep_alter_part_table() like the other callers there do. handle_alter_part_error() keeps a copy of DDL_LOG_STATE instead of the clone and passes it to write_log_completed() and release_log_entries(), which now take DDL_LOG_STATE. The redundant release_log_entries() after write_log_completed() is removed. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Monty
monty@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fixup! 0faa995f381086ee2b7105ed1b40a40a04a3ff43 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25176 Shutdown hangs if event scheduler is started during shutdown SET GLOBAL event_scheduler=1 executed by a connection during shutdown could start the scheduler thread after close_connections() called Events::stop(). Nothing stops this thread and close_connections() waits for it forever. Now it hangs instead of a crash since MDEV-30260 fix: it moved deinit() from close_connections() to clean_up(), so the scheduler is not freed under the running thread anymore. The fix makes Event_scheduler::start() do nothing when abort_loop is set. abort_loop is set before close_connections() and is checked under LOCK_scheduler_state, which stop() also takes, so the scheduler is either started before stop() and stopped by it, or not started at all. No error needed: the server is shutting down. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41541 uninitialized memory read in optimizer replay init all frequencies - not all of them might be present in the replay |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 Extract vers_set_starts() and add starts_clause Extracts the STARTS-alignment logic into vers_set_starts() so it can be reused. If the aligned local time falls into a DST gap (e.g. a midnight that does not exist), the start of the gap is used instead of failing with ER_PART_WRONG_VALUE. If it falls before the TIMESTAMP range (e.g. a local midnight before 1970), the timestamp itself is used. Also adds the Vers_part_info::starts_clause flag in preparation for later commits. The flag records whether STARTS was given explicitly (by the user or in the unpacked frm), which the auto-partitioning code uses to decide whether to re-align STARTS to the existing history. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dave Gosselin
dave.gosselin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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. When every top level base table was const and the join order ended with materialized semi-joins, the conjunct was never checked. Such a query gave wrong results. In that scenario the join returns at most one row, so the conjunct is now checked once before the join starts, together with the conditions on columns of an outer query. The decision uses the same search for the last top level base table that places the conjunct in every other case. A join of only const tables has no such table, and the same test covers it. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 Replace COMBINE macro with interval2sec() and interval2usec() Turn the COMBINE macro of date_add_interval() into inline functions with overloads for INTERVAL and MYSQL_TIME, so that the history partition sizing can reuse the seconds part. Move the "Daynumber" comment that sat above the macro to MAX_DAY_NUMBER, which it describes. MAX_DAY_NUMBER moves to sql_time.h as a constexpr (the unused copy in item_timefunc.cc is removed), and the range check of date_add_interval() becomes the inline interval_days_out_of_range(), so that the sizing can check that the seconds do not overflow. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Monty
monty@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
squash! 6e3fd9cbbca55c18f29a62850d0add915dbc71b5 - 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. - Reworked Master_use_gtid_value to remember users last choice and use this as default when connecting to slave. - Changed detection of current gtid state from a hidden function to a pointer to a variable. - 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 Using_git 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. Reviewer: Kristian Nielsen <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-25529 ALTER TABLE FORCE syntax improved Lets an alter_list be supplied alongside a partitioning or remove_partitioning clause in either order. This allows the FORCE clause to be added to an existing command, and lets AUTO and FORCE be specified together, which later commits of this task rely on. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aleksey Midenkov
midenok@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41545 Unchecked get_clone() in ALTER of partitioned table crashes on out-of-memory get_clone() returns NULL on out-of-memory, but two of its callers in prep_alter_part_table() dereferenced the result without a check, so the server crashed: changed INTERVAL of SYSTEM_TIME partitioning ADD PARTITION under LOCK TABLES get_clone() itself did not check the allocation of Vers_part_info and dereferenced it. handle_alter_part_error() did not check the clone either. The clone only kept the DDL log entries after the table is closed. In the branch where DDL log recovery fails, write_log_completed() released the entries through lpt->part_info, which the table close may have freed, and release_log_entries() released the same entries again through the clone. That branch is not reachable now, as ddl_log_execute_entry() always returns false. The fix checks the allocation of Vers_part_info in get_clone() and the result of get_clone() in prep_alter_part_table() like the other callers there do. handle_alter_part_error() keeps a copy of DDL_LOG_STATE instead of the clone and passes it to write_log_completed() and release_log_entries(), which now take DDL_LOG_STATE. The redundant release_log_entries() after write_log_completed() is removed. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Monty
monty@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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. 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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||