Console View
|
Categories: connectors experimental galera main |
|
| connectors | experimental | galera | main | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Added macro RPL_READ_FIELD_LENGTH which uses net_field_length_safe | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-870: Fix stack buffer overflow in ma_fcvt() ma_fcvt() had no destination-size parameter. Its zero-padding loop writes bytes proportional to the input value's magnitude, not its precision, so a large-magnitude double overflowed the fixed 300-byte buffer used by convert_from_float()/convert_from_double() in ma_stmt_codec.c (e.g. 1e308 with precision=30 needs 341 bytes). Add a to_size parameter to ma_fcvt() and bound every write, mirroring the existing pattern in ma_gcvt(). Update both call sites. Added test_ma_fcvt_bounded, covering the overflow scenario plus the decpt<=0 and DTOA_OVERFLOW branches directly. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41738 MEMORY BTREE: DELETE by key prefix skips rows Regression from MDEV-40186: for unique BTREE keys heap_rkey/rnext/rprev updated lastkey_len but not lastkey, so a scan restarted after DELETE searched from a stale key. Always save the found key in lastkey for BTREE indexes. Assisted-By: Claude Opus 5.5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 BACKUP SERVER: copy Aria tables from the open files The tables that are not safe for online backup were copied by name, after aria_open_files_for_backup() had opened and checked their files. A file could be replaced between the two opens, for example by a symbolic link that aria_open_files_for_backup() refuses. These tables are now copied from the open files, both at BACKUP_WAIT_FOR_FLUSH and, for the deferred tables in the mysql schema, at BACKUP_LOCK_COMMIT. Outside Windows, backup::copy_or_stream() copies a duplicate of the open file descriptor, so that the file can still be cloned or copied in the kernel. backup.backup_aria_symlink: tables with DATA DIRECTORY and INDEX DIRECTORY, and a table in a database directory that is a symbolic link, are backed up and restored. A .MAI or .MAD file that is a symbolic link into the data directory makes BACKUP SERVER fail. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Nikita Malyavin
nikitamalyavin@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39927 Multi-key read: batch index condition pushdown for non-parametrizeable series of ranges A join that reads a local table first and looks up a remote table by key pays for the remote table in round trips or in rows. Remote means that the engine keeps its data on other machines, so every request is a network round trip, and that it can evaluate a condition next to the data. Ref access sends one request per local row. BKA sends one MRR request for all buffered keys, but the engine returns every row that shares a key, and the server filters them by the local values afterwards. In SELECT w.sym, t.id, t.ts, t.price FROM watch w STRAIGHT_JOIN trades t ON t.sym = w.sym AND t.ts >= w.since AND t.price > w.min_price with 4 local watch rows, 200 trades rows share a sym with them and 10 satisfy the ON clause: BKA returns 200 rows, where an engine that evaluated the condition would return 10. No pushdown interface allows this, because none gives the engine a condition over the local values together with the values of every buffered row. cond_push sees only the table's own columns. Under BKA the server keeps an index condition over other tables to itself and evaluates it on each fetched tuple (cache_idx_cond, skip_index_tuple). Pushdown of a select or a derived table to the handlerton would make the engine read the local table itself. MRR knows which buffered row a range answers, but a range carries only its key. Solution: the server buffers the earlier tables' rows as BKA does and hands the engine one condition, pushdown, in which their values are parameters; then, call by call, it hands over the tuples of parameter values of the buffered rows. The engine prepares pushdown once and evaluates it for each tuple next to the data. Each row it returns names its tuple by offset, and the server maps the offset back to the buffered rows and rechecks them. JOIN_CACHE_MULTI_KEY, derived from JOIN_CACHE_BKA, takes BKA's place after the join order is fixed, on ref or eq_ref access to a table whose engine sets HA_CAN_MULTI_KEY_READ, when the new optimizer_switch flag join_cache_multi_key_read, off by default, is on. EXPLAIN adds "Multi-key read" after "Using join buffer (flat, BKA join)". The interface is three handler methods in the style of index condition pushdown; MRR is left untouched: index_multi_key_read_with_pushdown_prepare(index, param, params, pushdown) once per optimization for each execution of the join: ha_index_init(index) for each call a refill of the join buffer splits into: index_multi_key_read_params(row_data) index_multi_key_read(record, &offset) until HA_ERR_END_OF_FILE ha_index_end() Design: - pushdown is a deep copy of the conjuncts of the table's condition (for an inner table of an outer join, its ON expression) that use the remote table, and otherwise only the buffered and the const tables. It keeps the ref's key equality, one top-level = or <=> on each key part the ref uses, so the engine finds the key to look up and the residual to filter by in one condition. - Parameters are copies of the buffered tables' fields in a Virtual_tmp_table, param[] is its field array, and pushdown's Item_fields point at the copies. A const table's field stays a constant: a parameter is whatever is in param[]. - A tuple is a record of that table: the parameter values only, in fixed record format, so that tuples compare byte for byte. params() gets all tuples of a call at once, as a nullptr-terminated array in a buffer the server owns; the engine reads tuple i by moving param[] by row_data[i] - row_data[0]. - The server sorts the tuples by key, merges exact duplicates and sends tuples that share a key but differ in parameters in successive calls. So each returned row answers exactly one tuple, and the engine never deduplicates. Outer joins NULL-complement the unmatched buffered rows as under BKA. The server guarantees: - no NULL key value in a tuple; - no two tuples in one call with keys the index finds equal; - param[] at row_data[0] when params() starts; - a recheck of every returned row, except the key equalities test_if_ref leaves out and an index condition the engine accepted through idx_cond_push. The engine must: - answer prepare with 0 or HA_ERR_UNSUPPORTED, or raise its own error. prepare runs during optimization, EXPLAIN included, and an acceptance lasts across executions until the next prepare or reset(). It promises no call, so pushdown applies only to the rows read() returns; - not fail ha_index_init on an accepted index: what can fail belongs in params(); - read the values before params() returns and leave param[] at row_data[0]; - return for each tuple every row that satisfies pushdown, once. The key equalities must hold exactly, since the recheck may leave them out and the split into calls relies on them; the rest of pushdown may be applied loosely, except an index condition accepted through idx_cond_push; - end a call with HA_ERR_END_OF_FILE, as any other error fails the statement, and accept ha_index_end in the middle of a call. Otherwise the join runs as plain BKA, with the same rows, decided once per plan: when a key part's value is not the ref's own (it comes from the outer query, sits only inside an OR, appears twice, or equality propagation changed it); when a nullable key value meets a part that is not null-rejecting; when pushdown holds an item with no deep copy, such as a subquery or a stored function; when a parameter is a BLOB, a TEXT, or a BIT kept among the null bits; when there is no parameter, or none comes from an engine other than the remote table's (by partition_ht(), a derived or temporary table counting as local), since there BKA's one MRR request beats a call per tuple; and when prepare returns HA_ERR_UNSUPPORTED. Limitations: - The engine must support MRR. - A partitioned remote table is not supported: ha_partition masks the flag. Tests: this commit only re-records the results that list the optimizer_switch flags; with the flag off, the join-cache tests (main.join_cache, the *_jcl6 tests, main.mrr_icp_extra, main.innodb_mrr_cpk) pass unchanged. DBUG_EXECUTE_IF points simulate out of memory where the cache and the parameter copies are created. The next commit adds the test engine TEST_MULTI_KEY. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
test: replace memmem with local ma_memmem helper for portability Remove reliance on GNU memmem() in tests by using an internal helper, ensuring consistent test execution across Windows (MSVC) and POSIX. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| remove dead code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Kristian Nielsen
knielsen@knielsen-hq.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41867: Tablespace pre-allocation blocks SHOW BINARY LOGS The pre-allocation thread was holding purge_binlog_mutex while creating the next binlog tablespace file. The creation of the file can take a long time, and a _very_ long time if disk runs full and the function needs to wait for space to be freed. Holding the mutex for long blocks other commands from running such as SHOW BINARY LOGS, and even PURGE BINARY LOGS (which might otherwise be used to free up space needed). Holding the mutex across the file creation is unnecessary, the creation only happens from the single pre-allocation thread, and it doesn't reference any data that needs to be protected by that mutex. So just delay taking the mutex until after the file creation. Make the innodb_binlog_size_in_pages variable into an atomic. It is not protected by the purge_binlog_mutex (or any other mutex) anyway, and it is just the "current value" that can be changed by the user at any time. So using atomic is mostly to document the unsynchronised access. Signed-off-by: Kristian Nielsen <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-868: Fix out-of-bounds read in my_uca1400_collation_id_uca400_compat() my_uca1400_collation_id_uca400_compat() derives a tailoring id from a UCA-14.0.0 collation id and uses it to index a table of UCA-4.0.0 compatible collation ids. For tailoring ids 26..31 the lookup went past the end of that table and read adjacent memory. Check the tailoring id against the table size before indexing, and return 0 (no compatible id) for ids outside the table. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-863: Check that name offsets of dynamic columns do not decrease read_name() computed the length of a column name as the difference of two name offsets read from the packed column, without checking that the next offset is not smaller than the current one. The subtraction wrapped around, and mariadb_dyncol_list_named() passed the result as size to memcpy(). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 BACKUP SERVER: read the Aria index header under its locks The header blocks of an Aria index file have no page checksum, and the table state at their start is written with my_pwrite(), outside the page cache: by a checkpoint, by maria_close(), and on the first change after an open. A concurrent copy could read part of such a write, and the torn state would not be detected. aria_read_index_file() now reads the header blocks of a table that is safe for online backup in aria_read_header(), under THR_LOCK_maria, which maria_open() and maria_close() hold, and under MARIA_SHARE::intern_lock of the open table, which the other writers hold. The table is found by the real path of its index file, which ARIA_BACKUP_CONTEXT::index_name now stores. While the header is read, no Aria table can be opened or closed; this is one read of the header blocks per table. Not covered: _ma_mark_file_crashed() writes the 2-byte "changed" field without these locks. It runs only on an error path, when the table is already corrupted. mariabackup calls aria_read_index() directly and is not changed. backup.backup_aria_header: while BACKUP SERVER reads the header of an open table, the open of another Aria table waits for THR_LOCK_maria and the first write to the open table waits for SHARE::intern_lock. Without either lock, the test fails. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 test: Aria writes during a streamed BACKUP SERVER backup.backup_aria_stream_concurrent: BACKUP SERVER WITH 4 CONCURRENT 'cat' streams to 4 archives while one connection inserts into an Aria table that is safe for online backup, and another inserts into a TRANSACTIONAL=0 table and into a table without page checksums. The restored tables pass CHECK TABLE EXTENDED and each holds the rows 1..N with no gap. The test uses no debug instrumentation, so it also runs on release builds. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-869: Fix OOB read in dyncol value readers due to unvalidated interval lengths. hdr_interval_length() computed a dynamic column value's length as (next_entry_offset - hdr->offset) without validating either offset against the real size of the blob's data segment (hdr->data_size). type_and_offset_read_num()/_named() only reject an offset that exceeds what its encoding can represent, which has nothing to do with the actual data available. Reachable via mariadb_dyncol_unpack() and mariadb_dyncol_json(), causing OOB reads in dynamic_column_uint_read(), dynamic_column_double_read(), and ma_dynstr_append_quoted(). Fix hdr_interval_length() to validate both the current and next entry's offset against hdr->data_size, matching the server's mysys/ma_dyncol.c. Also fixes dynamic_column_get_internal(), which returned stale ER_DYNCOL_OK instead of ER_DYNCOL_FORMAT when find_column() detected the same kind of corrupted interval. Added tests covering both value readers and the quoting path via mariadb_dyncol_unpack()/mariadb_dyncol_json(), plus a direct test for the mariadb_dyncol_get_num()/find_column() path. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-i864: Fix memory leak in mariadb_dyncol_list_named() The result array is allocated before the column names are read. When a name cannot be read, the function returned ER_DYNCOL_FORMAT without freeing the array and without resetting *names, so the memory was leaked and the caller was left with a non-NULL pointer although the function reported an error. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 test: Aria log rotation before the end of the backup log backup.backup_aria_log_rotate: after BACKUP SERVER copied the table files, commits to a table that is safe for online backup continue until BACKUP_LOCK_COMMIT and make the log continue in at least two new files. The backup ends in the same log file as the server, and recovery of the backup applies these commits from the start checkpoint, over the whole log files, to the copied table files. The test fails when the log files before the file of the end are not copied. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-i860: Add STMT_ATTR_CB_RESULT_EX, a result callback with an end pointer STMT_ATTR_CB_RESULT passes only the current position in the row to the callback, so a callback cannot check that the data it parses is inside the row. Add STMT_ATTR_CB_RESULT_EX with the signature int callback(void *data, unsigned int column, unsigned char **row, const unsigned char *end); row points to the column's data (the length prefix for variable length types) and is NULL for NULL values. end is the first byte after the column's data. The callback must advance *row exactly to end. A non-zero return value, or a *row different from end, aborts the fetch with CR_MALFORMED_PACKET. The legacy and the new callback share storage in MYSQL_STMT (union), selected by a private type tag, so setting one replaces the other. Passing NULL clears the callback and returns to the bind_result path. mysql_stmt_attr_get() supports STMT_ATTR_CB_RESULT, STMT_ATTR_CB_RESULT_EX and STMT_ATTR_CB_PARAM. The getter for the inactive result callback returns NULL. Because older libraries reject unknown attributes, mysql_stmt_attr_get(stmt, STMT_ATTR_CB_RESULT_EX, &cb) can be used to detect support without side effects. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Nikita Malyavin
nikitamalyavin@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41238 mysqltest: add PS_bind_long command mysqltest gets a PS_bind_long command. It binds like PS_bind, but sends every value with mysql_stmt_send_long_data() before each PS_execute, so a test can reach a parameter in LONG_DATA_VALUE state. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41738 MEMORY BTREE: DELETE by key prefix skips rows Regression from MDEV-40186: for unique BTREE keys heap_rkey/rnext/rprev updated lastkey_len but not lastkey, so a scan restarted after DELETE searched from a stale key. Always save the found key in lastkey for BTREE indexes. Assisted-By: Claude Opus 5.5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update C/C | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Nikita Malyavin
nikitamalyavin@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39927 Multi-key read: test engine TEST_MULTI_KEY No engine in the server tree implements the multi-key read, so no test in the tree takes the path. TEST_MULTI_KEY is a MEMORY engine that does: for each tuple, its read looks up the tuple's key and returns the rows the pushed condition admits. Session variables count its prepares, calls, tuples and rows. Its suite test_multi_key runs each query with join_cache_multi_key_read off, through SET STATEMENT, and then on, and shows the counters and the EXPLAIN of the path. The case with a ? takes the path because of MDEV-41238, which gives a bound ? a copy. ha_heap is no longer final and is exported from mariadbd, as ha_maria is, so that the dynamic plugin can derive from it. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch '3.3-serg' into 3.3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Nikita Malyavin
nikitamalyavin@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41238 follow-up: widen the assertion in Item_param::shallow_copy() On main, Query_arena::free_items() makes a debug-only shallow copy of each item class it frees (MDEV-41631). When reprepare frees the old items of a prepared statement, the statement arena is the THD's own conventional one, so the assertion against copying an Item_param on the statement arena fired: main.ps_ddl crashed in debug builds. This is the way a conventional arena reaches an Item_param, which the review of PR #5906 left open. Solution: the assertion that review suggested, which lets a conventional arena pass; a copy on a prepared statement's arena still fails it. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Bug fix for MYSQL: Use DATETIME intead of TIME | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 BACKUP SERVER: end the Aria log after the table copy The Aria log was copied at the start of BACKUP_LOCK_COMMIT, while commits were blocked, and before the deferred mysql tables were copied. Its end was the horizon at that time. maria_backup_end(BACKUP_LOCK_COMMIT) now determines the end of the log in the backup (maria_backup_context::end_lsn), after all table files were copied, and flushes the log up to it. Commits are blocked only for this. maria_backup_start(BACKUP_FINISHED) copies the log after the locks were released: the files before the file of the end as a whole, and the last file up to the page of the end. The log continues to grow after the end. The pages before the page of the end do not change. translog_cut_page() changes the page of the end to the page that translog_flush() wrote when the end was the horizon: the bytes from the end are filled with TRANSLOG_FILLER, and the page checksum is computed again. A page with sector protection is rejected; the server does not write it (TRANSLOG_DEFAULT_FLAGS). No log rotation is needed. backup.backup_aria_log_end, based on a test case by Marko Mäkelä: after the end of the log, an UPDATE writes log records and data pages while its commit waits for the backup lock. Before the log is copied, the UPDATE commits and more writes make the log continue in a new file. The backup contains none of these changes, ends in the log file of the end, and the restored server continues the log from the cut page after a kill. If the end is taken at BACKUP_FINISHED instead, the test fails. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 test: Aria inserts during BACKUP SERVER, no debug needed backup.backup_aria_concurrent_insert: BACKUP SERVER runs while another connection commits one row at a time to an Aria table that is safe for online backup, with a small page cache and small log files. The restored table passes CHECK TABLE EXTENDED and holds the rows 1..N with no gap, with N not more than the rows after BACKUP SERVER returned. The test uses no DEBUG_SYNC or DBUG keywords, so it also covers release builds, where the Aria log pages have no checksum. The writer stops when the user lock "run" is released, not on KILL QUERY: when the kill arrives after a statement of the procedure has sent its OK, mysql_execute_command() discards it, and the procedure continues. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Nikita Malyavin
nikitamalyavin@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41238 Bound parameters prevent condition pushdown into a grouped view, while CAST enables it Item_param::deep_copy() returned NULL, and every rewrite that copies a condition gives up on what it cannot copy. A conjunct holding a prepared statement parameter was therefore left out of: - pushdown into derived tables and views, including UNION branches and conditions on a derived table column whose expression holds a parameter; - pushdown from HAVING to WHERE, for the part extracted from an OR; - pushdown into a materialized IN subquery; - split materialization, which then found no split key; - the UPPER(col) IN (...) rewrite, which has skipped such conjuncts since MDEV-40006. When the derived table groups by an expression with a parameter, the condition was pushed into its HAVING instead of its WHERE. CAST(? AS ...) worked around this only by accident. Before the pushdown, constant propagation can replace a constant expression on one side of = with a literal. A bare parameter already counts as a basic constant, so propagation leaves it as it is. A client whose charset differs from the column's got the pushdown by a similar accident: the charset conversion replaces the parameter with a literal. Item_param::shallow_copy() now copies a parameter that holds a value, NULL included, and deep_copy() calls it, as in other leaf items. Every such copy is made while optimizing during EXECUTE, and the next EXECUTE makes a new one, so a copy always carries the value bound for the EXECUTE that made it. A copy that outlived its EXECUTE would keep an old value and point into a string buffer that the next binding may free, so shallow_copy() asserts that it does not allocate on the statement's arena. The copy is not added to m_clones. m_clones keeps the parameter's copies in CTE definitions updated with each new value for the whole life of the statement, while this copy lives for one execution. An unbound parameter, DEFAULT and IGNORE still have no copy. On main the new derived_cond_pushdown cases record key_length 260 and rows 20 where 11.4 records 68 and 10, since the default character set is utf8mb4, and the CTE case estimates rows 1 for the ref into <derived3> where 11.4 estimates 10. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aria: ma_commit() flushes the log up to an uninitialized LSN If translog_write_record() failed for the COMMIT record, ma_commit() still called translog_flush(commit_lsn), with commit_lsn not initialized. The | operator was there so that trnman_commit_trn() is always called; that call is a separate statement since 91bc9cc9e66. Call translog_flush() only if the COMMIT record was written, as the other callers of translog_write_record() do. Under Valgrind, maria.aria_log_create_error reports the uninitialized value without this change. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Aria: double free after a failed log file creation translog_create_new_file() adds the new TRANSLOG_FILE to log_descriptor.open_files before it creates the file. If the creation failed, the error path freed the object but left the pointer in open_files. If translog_write_file_header() or ma_control_file_write_and_force() failed, the error path freed the object that open_files already owned. In both cases, translog_destroy() closed and freed the object again at shutdown: "Error on close of '(null)'", followed by heap corruption. Remove the pointer from open_files if the file creation fails. Do not free the object after open_files owns it. The test needs a non-debug build, because translog_stop_writing() fails a debug assertion. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-14992 BACKUP SERVER: do not allocate a buffer for an empty file pread_write() allocated its copy buffer with aligned_malloc(0) when it copied or streamed an empty file. Valgrind reports a zero-size allocation ("Unsafe allocation with size of zero"), for example in backup.backup_aria_stream_concurrent. pread_write() now returns at once when there is nothing to copy. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alessandro Vetere
iminelink@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39092 BACKUP SERVER: fail if the Aria log is read-only After a log write error, the Aria log is read-only and translog_flush() returns success without writing. The log files can then end before the end of the backup log, which maria_backup_end(BACKUP_LOCK_COMMIT) sampled. The log copy could succeed while recovery of the backup stops before that end, with data pages from after it. Fail with ER_ERROR_ON_WRITE if the log is not in the TRANSLOG_OK state. The test needs a non-debug build, because translog_stop_writing() fails a debug assertion. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Nikita Malyavin
nikitamalyavin@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39927 Multi-key read: test engine TEST_MULTI_KEY No engine in the server tree implements the multi-key read, so no test in the tree takes the path. TEST_MULTI_KEY is a MEMORY engine that does: for each tuple, its read looks up the tuple's key and returns the rows the pushed condition admits. Session variables count its prepares, calls, tuples and rows. Its suite test_multi_key runs each query with join_cache_multi_key_read off, through SET STATEMENT, and then on, and shows the counters and the EXPLAIN of the path. The case with a ? takes the path because of MDEV-41238, which gives a bound ? a copy. ha_heap is no longer final and is exported from mariadbd, as ha_maria is, so that the dynamic plugin can derive from it. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Add placeholder in emum_stmt_attr_type Since value 207 (STMT_ATTR_SQL_STATEMENT) is already used in 3.4 we have to add a placeholder (STMT_ATTR_UNUSED). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rucha Deodhar
rucha.deodhar@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41812: Columns named old/new of other tables are resolved as the OLD/NEW row inside trigger bodies, giving ER_TRG_NO_SUCH_ROW_IN_TRG and ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION Analysis: Inside the trigger's BEGIN...END block, impossible fields are not checked and the mechanism directly falls on checking whether it is new or old reference. Fix: Check whether the fields are impossible and only then resolve the context of new and old. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Nikita Malyavin
nikitamalyavin@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39927 Multi-key read: batch index condition pushdown for non-parametrizeable series of ranges A join that reads a local table first and looks up a remote table by key pays for the remote table in round trips or in rows. Remote means that the engine keeps its data on other machines, so every request is a network round trip, and that it can evaluate a condition next to the data. Ref access sends one request per local row. BKA sends one MRR request for all buffered keys, but the engine returns every row that shares a key, and the server filters them by the local values afterwards. In SELECT w.sym, t.id, t.ts, t.price FROM watch w STRAIGHT_JOIN trades t ON t.sym = w.sym AND t.ts >= w.since AND t.price > w.min_price with 4 local watch rows, 200 trades rows share a sym with them and 10 satisfy the ON clause: BKA returns 200 rows, where an engine that evaluated the condition would return 10. No pushdown interface allows this, because none gives the engine a condition over the local values together with the values of every buffered row. cond_push sees only the table's own columns. Under BKA the server keeps an index condition over other tables to itself and evaluates it on each fetched tuple (cache_idx_cond, skip_index_tuple). Pushdown of a select or a derived table to the handlerton would make the engine read the local table itself. MRR knows which buffered row a range answers, but a range carries only its key. Solution: the server buffers the earlier tables' rows as BKA does and hands the engine one condition, pushdown, in which their values are parameters; then, call by call, it hands over the tuples of parameter values of the buffered rows. The engine prepares pushdown once and evaluates it for each tuple next to the data. Each row it returns names its tuple by offset, and the server maps the offset back to the buffered rows and rechecks them. JOIN_CACHE_MULTI_KEY, derived from JOIN_CACHE_BKA, takes BKA's place after the join order is fixed, on ref or eq_ref access to a table whose engine sets HA_CAN_MULTI_KEY_READ, when the new optimizer_switch flag join_cache_multi_key_read, off by default, is on. EXPLAIN adds "Multi-key read" after "Using join buffer (flat, BKA join)". The interface is three handler methods in the style of index condition pushdown; MRR is left untouched: index_multi_key_read_with_pushdown_prepare(index, param, params, pushdown) once per optimization for each execution of the join: ha_index_init(index) for each call a refill of the join buffer splits into: index_multi_key_read_params(row_data) index_multi_key_read(record, &offset) until HA_ERR_END_OF_FILE ha_index_end() Design: - pushdown is a deep copy of the conjuncts of the table's condition (for an inner table of an outer join, its ON expression) that use the remote table, and otherwise only the buffered and the const tables. It keeps the ref's key equality, one top-level = or <=> on each key part the ref uses, so the engine finds the key to look up and the residual to filter by in one condition. - Parameters are copies of the buffered tables' fields in a Virtual_tmp_table, param[] is its field array, and pushdown's Item_fields point at the copies. A const table's field stays a constant: a parameter is whatever is in param[]. - A tuple is a record of that table: the parameter values only, in fixed record format, so that tuples compare byte for byte. params() gets all tuples of a call at once, as a nullptr-terminated array in a buffer the server owns; the engine reads tuple i by moving param[] by row_data[i] - row_data[0]. - The server sorts the tuples by key, merges exact duplicates and sends tuples that share a key but differ in parameters in successive calls. So each returned row answers exactly one tuple, and the engine never deduplicates. Outer joins NULL-complement the unmatched buffered rows as under BKA. The server guarantees: - no NULL key value in a tuple; - no two tuples in one call with keys the index finds equal; - param[] at row_data[0] when params() starts; - a recheck of every returned row, except the key equalities test_if_ref leaves out and an index condition the engine accepted through idx_cond_push. The engine must: - answer prepare with 0 or HA_ERR_UNSUPPORTED, or raise its own error. prepare runs during optimization, EXPLAIN included, and an acceptance lasts across executions until the next prepare or reset(). It promises no call, so pushdown applies only to the rows read() returns; - not fail ha_index_init on an accepted index: what can fail belongs in params(); - read the values before params() returns and leave param[] at row_data[0]; - return for each tuple every row that satisfies pushdown, once. The key equalities must hold exactly, since the recheck may leave them out and the split into calls relies on them; the rest of pushdown may be applied loosely, except an index condition accepted through idx_cond_push; - end a call with HA_ERR_END_OF_FILE, as any other error fails the statement, and accept ha_index_end in the middle of a call. Otherwise the join runs as plain BKA, with the same rows, decided once per plan: when a key part's value is not the ref's own (it comes from the outer query, sits only inside an OR, appears twice, or equality propagation changed it); when a nullable key value meets a part that is not null-rejecting; when pushdown holds an item with no deep copy, such as a subquery or a stored function; when a parameter is a BLOB, a TEXT, or a BIT kept among the null bits; when there is no parameter, or none comes from an engine other than the remote table's (by partition_ht(), a derived or temporary table counting as local), since there BKA's one MRR request beats a call per tuple; and when prepare returns HA_ERR_UNSUPPORTED. Limitations: - The engine must support MRR. - A partitioned remote table is not supported: ha_partition masks the flag. Tests: this commit only re-records the results that list the optimizer_switch flags; with the flag off, the join-cache tests (main.join_cache, the *_jcl6 tests, main.mrr_icp_extra, main.innodb_mrr_cpk) pass unchanged. DBUG_EXECUTE_IF points simulate out of memory where the cache and the parameter copies are created. The next commit adds the test engine TEST_MULTI_KEY. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Infer fixes (dead code) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Georg Richter
georg@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-861: Bounds checks for length-encoded integers and binary rows Add net_field_length_safe()/net_field_length_ll_safe(), which take an end pointer, reject 0xFF, truncated prefixes and 32-bit overflow, and optionally reject the NULL marker (MARIADB_LENENC_FORBID_NULL). Export mariadb_net_field_length() (version node libmariadb_3_3_22). Use the checked decoders in cli_report_progress(), mthd_my_read_query_result(), mthd_my_read_one_row(), mysql_list_processes(), mthd_stmt_read_all_rows(), mthd_stmt_flush_unbuffered() and mthd_stmt_fetch_to_bind(). mthd_stmt_fetch_to_bind() now owns the column boundary: it validates the length prefix and the lengths of temporal types, and resyncs the row pointer after callbacks and conversion functions. Behavior changes: malformed text rows report CR_MALFORMED_PACKET instead of CR_UNKNOWN_ERROR; EOF packets shorter than 5 bytes are rejected. Assisted by Claude |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| update C/C | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Golubchik
serg@mariadb.org |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
compilation error libmariadb\unittest\libmariadb\internal.c(295,21): error C2124: divide or mod by zero double inf= 1.0 / 0.0; /* or use INFINITY from <math.h> if preferred */ ^ |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rucha Deodhar
rucha.deodhar@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41812: Columns named old/new of other tables are resolved as the OLD/NEW row inside trigger bodies, giving ER_TRG_NO_SUCH_ROW_IN_TRG and ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION Analysis: Current implementation did not check whether fields are impossible (no select involved). This made columns named "old" or "new" falsely recognized as trigger row references. Fix Fixed the condition to check fields_are_impossible() so that column names can be correctly recognized. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||