Console View
|
Categories: connectors experimental galera main |
|
| connectors | experimental | galera | main | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
bsrikanth-mariadb
srikanth.bondalapati@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MDEV-42044: Check table privileges for the context recorder when trace is off | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
rusher
diego.dupin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
CONC-878: Skip the parameter definitions of a prepare response without copying them mthd_stmt_get_param_metadata() built a MYSQL_DATA row set from the parameter definition packets of the COM_STMT_PREPARE response and freed it right away, since parameter metadata is not exposed. Read exactly param_count packets and drop them, then the EOF packet, which is still used to update the warning count and the server status as in mthd_my_read_rows(). A missing or extra packet is reported as a malformed packet. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-38741 Abort the running statement when its client disconnects A watcher thread subscribes to the OS notification that a client has gone (e.g. TCP FIN or RST for a TCP socket, a gone client process for a named pipe) and aborts the running statement like KILL CONNECTION does. Controlled by the global variable disconnect_watcher. Details in PR#6035. Assisted-by: Claude:claude-sonnet-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
sjaakola
seppo.jaakola@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41597: GRANT ROLE is replicated before the privilege check GRANT ROLE and REVOKE ROLE started TOI before mysql_grant_role() checked whether the user may grant the role, and they could be replicated, although they potentially could be refused on the originating node later on. On the other nodes the applier runs with a non-user security context, and GRANT and REVOKE ROLE, will be applied causing the nodes' ACLs to be diverged. Begin TOI is moved inside mysql_grant_role(), after the role lookup and the privilege check. The check is done by a new helper, find_grantable_role(), which is also used for the second check under LOCK_grant. Under TOI the second check only looks up the role again and does not repeat the privilege check. Otherwise an ACL change ordered between the first check and the start of TOI (e.g. REVOKE ADMIN OPTION from the granting user) could refuse the statement on the originating node only, while the other nodes apply it. The pre-TOI check is therefore final in a cluster, as it already is for the other ACL statements: privileges are checked as of the start of the statement. Without wsrep, or outside TOI, both checks are done as before. A DEBUG_SYNC point, grant_role_before_toi, is added before TOI begins. The test galera.MDEV-41597 checks that: - a GRANT ROLE refused on node_1 is not applied on node_2 - when REVOKE ADMIN OPTION is ordered between the privilege check and the start of TOI, both nodes reach the same outcome |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
rusher
diego.dupin@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge branch '3.4-stmt-prepare-skip-params' into 3.4-perf | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Jan Lindström
jan.lindstrom@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-31300 Suppress RESET SLAVE's Using_Gtid note across galera tests RESET SLAVE/RESET SLAVE ALL emits a Note when it changes Using_Gtid, and whether it does depends on the prior value, which can drift with unrelated replication changes - galera_query_cache_invalidate, galera_2_cluster and galera_gtid_2_cluster depend on it appearing. Wrap every RESET SLAVE/RESET SLAVE ALL across the galera and galera_3nodes suites in --disable_warnings/--enable_warnings, so no test depends on that value. Assisted-by: Claude:claude-4.6-sonnet |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Pekka Lampio
pekka.lampio@galeracluster.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-38999 followup: fix galera_sr.mysql-wsrep#215 regression wsrep_must_sync_wait() now performs the causal wait on the first real statement of an explicit transaction instead of skipping it as soon as the transaction was merely BEGIN'd. mysql-wsrep#215 deliberately freezes node_1's local applier via a debug sync point and then expects node_1's own first statement in the transaction to proceed without waiting for that frozen apply - which the old, buggy skip-on-BEGIN behaviour happened to allow, but the fix correctly no longer does. Disable wsrep_sync_wait for node_1's session before entering the transaction, mirroring the same workaround node_1a's connection already uses for the identical reason. Co-Authored-By: Claude Sonnet 5 <[email protected]> |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Elena Stepanova
elenst@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42198 Options from MTR opt files are added multiple times Options from .opt files of included files were appended every time the file was sourced, so they got repeated once per include path. It caused unnecessary server restarts, and too long server command lines lead to startup failures on Windows. Now each file caches only its own .opt options plus an ordered list of the files (itself and everything it sources) whose options apply, each file listed once. The test's options are assembled from that list. Options of included files still precede those of the including file. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
bsrikanth-mariadb
srikanth.bondalapati@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42044: Do the table privilege check once for trace and recorder Run opt_trace_disable_if_no_tables_access() once in mysql_execute_command(), after the recorder is created, instead of separately at trace start and in the recorder. Remove opt_ctx_can_read_all_columns(). The recorder now relies on its missing_priv flag and skips recording when it is set. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Petrunia
sergey@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42216: Optimizer Trace shows INSUFFICIENT_PRIVILEGES for sequences opt_trace_disable_if_no_tables_access() checks if optimizer trace contents would provide the user with something that otherwise the user won't have access to. For tables, the requirement is that the user has per-table SELECT right to the table (access to certain columns is not sufficient). The check doesn't work for sequences that are used through NEXTVAL, CURVAL, etc. They have a special permission check done at fix_fields() phase, they do not have per-table vs per-column distinction. Disable the check here. If the user doesn't have SELECT right for the sequence, the query will fail and the trace will only list "join_preparation" step. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Rex Johnston
rex.johnston@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39492 PQ: a worker's join buffers are allocated on the worker's thread In a debug build main.parallel_query_join aborted in the worker THD's destructor: status_var.local_memory_used was not zero, and safemalloc reported the join buffer and its field descriptors as freed by a worker thread but allocated by the query thread. The manager built each worker's JOIN_CACHE in setup_worker_jointabs() and called init() there, on the query thread. init() allocates the buffer with my_malloc(MY_THREAD_SPECIFIC) and the field descriptors on the cache's JOIN's THD, the worker's. A thread-specific allocation is charged to current_thd at the time, the manager's THD, while the free -- the buffer in pwt_worker::close_tables(), the descriptors when the worker THD's mem_root is torn down -- is credited to the worker's THD on the worker's thread. Each THD's count ended up off by the buffer in opposite directions, and ~THD asserts on a non-zero count. The cache object is still built by the manager, on the statement's mem_root, with the previous tab chained and the trackers attached. init() now runs at the start of pwt_worker::execute_and_handoff(), on the worker's thread, in tab order, before anything is locked, so a failure has nothing to undo and is reported as out of memory through the worker's error path. The allocation and the free are then made by the same thread and charged to the same THD. This commit was prepared with Claude Code (Fable 5.1), which reproduced the assertion under mtr, resolved the safemalloc allocation stacks to JOIN_CACHE::init() called from setup_worker_jointabs(), moved the init() call to the worker thread, and verified the 24 parallel_query tests pass in both protocols on the debug build. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Jan Lindström
jan.lindstrom@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-31300 Suppress RESET SLAVE's Using_Gtid note across galera tests RESET SLAVE/RESET SLAVE ALL emits a Note when it changes Using_Gtid, and whether it does depends on the prior value, which can drift with unrelated replication changes - galera_query_cache_invalidate, galera_2_cluster and galera_gtid_2_cluster depend on it appearing. Wrap every RESET SLAVE/RESET SLAVE ALL across the galera and galera_3nodes suites in --disable_warnings/--enable_warnings, so no test depends on that value. Assisted-by: Claude:claude-4.6-sonnet |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Elena Stepanova
elenst@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41085 Enable MTR tests on Windows: rpl suite rpl.rpl_row_mysqlbinlog fails because apparently the client command line on Windows cannot interpret the literal cp932 string which is passed to it. Since the point of the test is not how the original INSERT happens, but how it further works while replaying the binlog, it should be acceptable to insert a hex-encoded value |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Susil
susil.behera@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41446 rpl.rpl_fragment_row_event_main: wait for binlog checkpoint The test failed in buildbot with a result content mismatch: in Test Case 7 the Binlog_checkpoint event naming the current binlog was listed after the CREATE TABLE events instead of before them. That event is logged asynchronously, normally by the binlog background thread, once the previous binlog has been checkpointed, so its position among the first events of a freshly rotated binlog depends on timing. Test Case 7 lists the events of the binlog opened by the FLUSH LOGS at the end of the previous test case, without waiting for that event. The other listings of this test wait for it, in rpl_fragment_row_event.inc, with include/wait_for_binlog_checkpoint.inc. Wait for the checkpoint event in the same way before the CREATE TABLE in Test Case 7. The listed checkpoint rows can also differ in a second way. show_binlog_events.inc skips the first Binlog_checkpoint of a binlog, which normally names the previous binlog. If a FLUSH LOGS runs before the background thread has logged the checkpoint of the previous one, that skipped event names an older binlog, and the checkpoint naming the previous binlog is listed as an extra row. The cleanup at the end of rpl_fragment_row_event.inc runs FLUSH LOGS shortly after the FLUSH LOGS of its last test phase, without waiting in between. Wait for the checkpoint before each of the three cleanup FLUSH LOGS (one per server). The recorded result is unchanged. Verified with the debug point inject_binlog_background_thread_before_mark_xid_done, which holds back one checkpoint event: with the event of the cleanup FLUSH LOGS held back, only the wait in Test Case 7 prevents the diff reported in the bug; with the event of the FLUSH LOGS before it held back, only the cleanup waits prevent the extra row. Both changes together pass in both cases. The same ordering variance failed binlog.binlog_checkpoint, see MDEV-29607. Assisted-by: Claude:claude-sonnet-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
bsrikanth-mariadb
srikanth.bondalapati@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42044: Fix Optimizer Context privilege checks Follow-up to the previous MDEV-42044 commit: * opt_trace_disable_if_no_security_context_access() returned early when the optimizer trace was not started, so a context recorded through DEFINER routines, triggers or views was never marked as restricted. Mark the recorder before that return. * Skip the access checks when built with NO_EMBEDDED_ACCESS_CHECKS. * Factor the repeated "missing privilege" code in opt_trace.cc into helpers. Tests: assert the "Insufficient privileges" output, and add cases for column-level grants, an unexecuted function, a DEFINER trigger, optimizer_trace=ON, and a privileged user who still gets a full context. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42049 MTR server-cert.pem has no DNS SAN, fails on OpenSSL 4.1 OpenSSL 4.1 no longer matches a host name against the subject CN when the certificate has no DNS subjectAltName. Re-sign server-cert.pem with subjectAltName=DNS:localhost, and add it to generate-ssl-certs.sh. main.ssl_7937, main.ssl_system_ca and rpl.rpl_ssl1 fail with OpenSSL 4.1 without this change. The SHA1 fingerprint changes. main.ssl_fp (11.4+) must be updated when merging up: F1:D0:08:AF:A1:D2:F4:15:79:B4:39:06:41:F4:20:96:F1:90:A9:65 -> AE:F0:29:15:F1:9E:A0:A0:69:FB:83:20:B9:30:E3:DE:2F:25:2C:37 Assisted-by: Claude:claude-sonnet-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
bsrikanth-mariadb
srikanth.bondalapati@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MDEV-42044: Create the context recorder before the trace privilege checks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Vladislav Vaintroub
vvaintroub@gmail.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-38741 mtr: do not suppress the reason of a client disconnect The global suppressions of "Aborted connection", in mariadb-test-run.pl and mtr_warnings.sql, hid the line that the client disconnect watcher writes when it aborts a command: "Aborted connection N to db: 'x' user: 'u' host: 'h' (Client disconnected)". Nothing showed when the watcher aborted a connection that it should have left alone. main.locale found one, because its server log is in German and the English entry did not match. Make the two entries skip a line that ends in "(Client disconnected)". Other aborted connections are suppressed as before. The tests that drop a client on purpose accept the reason with mtr.add_suppression(), details in PR#6035. Assisted-by: Claude:claude-sonnet-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alexander Barkov
bar@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39563 Implement UPDATE ... RETURNING ... INTO Adding support for UPDATE .. RETURNING .. INTO queries. For example: UPDATE t1 SET a=10,b=20 RETURNING a,b INTO va,vb; UPDATE t1 SET a=10,b=20 RETURNING a,b INTO @a,@b; Limitations: 1. These types of queries: - REPLACE .. RETURNING .. INTO - DELETE .. RETURNING .. INTO - INSERT .. RETURNING .. INTO do not work - they return an error. They will be implemented separately, when needed. 2. UPDATE..RETURNING..INTO with --binlog_format=statement is not allowed and an error is raised. 3. Using OLD_VALUE(col) inside UPDATE..RETURNING..INTO is not allowed and an error is raised. 4. Multi-table updates, as well as single table updates with a subquery to the same table in WHERE (which get converted to multi-table) do not work and an error is raised. 5. UPDATE IGNORE .. RETURNING .. INTO is not supported for storage engines that can send updates later (Spider), because it is not known if the row was rejected. ER_NOT_SUPPORTED_YET is raised. Notes: 1. ANALYZE and EXPLAIN Both ANALYZE UPDATE .. RETURNING .. INTO .. EXPLAIN UPDATE .. RETURNING .. INTO .. return this error: 'RETURNING..INTO' is not allowed in this context 2. Behavior on no data and on multiple rows Only the rows that were actually changed are processed. A row that matches the WHERE condition but needs no update is not changed, so it is not returned by plain RETURNING either. Situation | RETURNING | RETURNING .. INTO -----------------------------+------------------+----------------------------- Empty table, WHERE matches | empty set | Warning ER_SP_FETCH_NO_DATA, nothing, WHERE 1=0, LIMIT 0 | | target is not changed One row matches, needs no | empty set | Warning ER_SP_FETCH_NO_DATA, update | | target is not changed Several rows match, none | empty set | Warning ER_SP_FETCH_NO_DATA, needs an update | | target is not changed | | (no ER_TOO_MANY_ROWS) One row matches and is | that row | Target is assigned changed | | Several rows match, exactly | that row | Target is assigned from one changes | | that row Two or more rows change | all changed rows | ER_TOO_MANY_ROWS at the 2nd | | changed row (not updated) Notes: - The warning is never an error: not in the strict mode, not with sql_mode='', not with IGNORE. The INTO targets keep their old values. In stored routines the warning activates NOT FOUND handlers. - This is the same for all storage engines, including those that quickly know the table is empty and use a degenerated plan (e.g. MyISAM). - After ER_TOO_MANY_ROWS, transactional engines roll back the statement, non-transactional engines keep the rows updated before the error (the second changed row is not updated). - The targets can be user variables, SP variables, ROW variables and ROW fields. 3. Behavior on VIEW with CHECK OPTION The "too many rows" check is done after the view's CHECK OPTION check. With UPDATE IGNORE, a row rejected by WITH CHECK OPTION is skipped (with a warning) and does not count as an updated row, so UPDATE IGNORE .. RETURNING .. INTO does not raise ER_TOO_MANY_ROWS if only one row is actually updated. 4. Behavior of UPDATE IGNORE .. RETURNING .. INTO With IGNORE, a row rejected by the storage engine (a duplicate key, no partition for the new values, a foreign key violation) is not changed, so it is not counted as a changed row, in the same way as for plain UPDATE IGNORE .. RETURNING. The engine decides about this in ha_update_row(), so the check for the second changed row is done after it: - Transactional engines: ER_TOO_MANY_ROWS rolls back the statement. - Non-transactional engines: the second row is updated back (including its BLOB values) before ER_TOO_MANY_ROWS is raised. Both updates are written to the binary log. Without IGNORE the check is done before the second row is updated. Helper changes: 1. The grammar in analyze_stmt_command was changed to have LEX::analyze_stmt set to true earlier, so LEX::set_returning_into_result() already knows if this is an ANALYZE statement. 2. The Sql_cmd_update constructor is now called earlier in the grammar, to be able to call Sql_cmd_update::set_with_old_value_items() in the SET and RETURNING clauses. 3. Sql_cmd_dml::lex is now set during the constructor time. It makes things easier: - Sql_cmd_update::returns_result_set() needs the lex. - Sql_cmd_delete::orig_multitable and Sql_cmd_update::orig_multitable are not needed any more. They were used only in Sql_cmd_delete::sql_command_code() and Sql_cmd_update::sql_command_code(). Sql_cmd_dml::sql_command_code() now returns lex->sql_command. The overrides Sql_cmd_delete::sql_command_code() and Sql_cmd_update::sql_command_code() were removed. 4. A new virtual method handler::update_may_be_deferred() tells if ha_update_row() can return success for a row that the engine rejects later. It is overridden in Spider and in ha_partition. This commit also fixes bugs found during testing: - MDEV-41262 ER_TOO_MANY_ROWS should be checked after CHECK OPTION in view while Update Returning Into - MDEV-41265 SELECT/ UPDATE RETURNING INTO a single row-field fails with ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, even though the column count matches This bug was also fixed in 12.3.4. - MDEV-41260 Misleading message text "uses a LIMIT clause" after Update Returning Into - MDEV-42212 UPDATE ... RETURNING ... INTO raises ER_TOO_MANY_ROWS on InnoDB when the second found row needs no update - MDEV-42156 UPDATE IGNORE ... RETURNING ... INTO fails with ER_TOO_MANY_ROWS when the second row is skipped by IGNORE (duplicate key) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alexander Barkov
bar@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39563 Implement UPDATE ... RETURNING ... INTO Adding support for UPDATE .. RETURNING .. INTO queries. For example: UPDATE t1 SET a=10,b=20 RETURNING a,b INTO va,vb; UPDATE t1 SET a=10,b=20 RETURNING a,b INTO @a,@b; Limitations: 1. These types of queries: - REPLACE .. RETURNING .. INTO - DELETE .. RETURNING .. INTO - INSERT .. RETURNING .. INTO do not work - they return an error. They will be implemented separately, when needed. 2. UPDATE..RETURNING..INTO with --binlog_format=statement is not allowed and an error is raised. 3. Using OLD_VALUE(col) inside UPDATE..RETURNING..INTO is not allowed and an error is raised. 4. Multi-table updates, as well as single table updates with a subquery to the same table in WHERE (which get converted to multi-table) do not work and an error is raised. 5. A row that looks changeable but is rejected by the engine (IGNORE with a duplicate key, no partition or foreign key violation) is still counted as found, so ER_TOO_MANY_ROWS can be raised while plain RETURNING returns only one row. Engines with batched updates (Spider) may return a row that was not changed. See MDEV-42156. Notes: 1. ANALYZE and EXPLAIN Both ANALYZE UPDATE .. RETURNING .. INTO .. EXPLAIN UPDATE .. RETURNING .. INTO .. return this error: 'RETURNING..INTO' is not allowed in this context 2. Behavior on no data and on multiple rows Only the rows that were actually changed are processed. A row that matches the WHERE condition but needs no update is not changed, so it is not returned by plain RETURNING either. Situation | RETURNING | RETURNING .. INTO -----------------------------+------------------+----------------------------- Empty table, WHERE matches | empty set | Warning ER_SP_FETCH_NO_DATA, nothing, WHERE 1=0, LIMIT 0 | | target is not changed One row matches, needs no | empty set | Warning ER_SP_FETCH_NO_DATA, update | | target is not changed Several rows match, none | empty set | Warning ER_SP_FETCH_NO_DATA, needs an update | | target is not changed | | (no ER_TOO_MANY_ROWS) One row matches and is | that row | Target is assigned changed | | Several rows match, exactly | that row | Target is assigned from one changes | | that row. But see | | Limitation 5. Two or more rows change | all changed rows | ER_TOO_MANY_ROWS at the 2nd | | changed row (not updated) Notes: - The warning is never an error: not in the strict mode, not with sql_mode='', not with IGNORE. The INTO targets keep their old values. In stored routines the warning activates NOT FOUND handlers. - This is the same for all storage engines, including those that quickly know the table is empty and use a degenerated plan (e.g. MyISAM). - After ER_TOO_MANY_ROWS, transactional engines roll back the statement, non-transactional engines keep the rows updated before the error. - The targets can be user variables, SP variables, ROW variables and ROW fields. 3. Behavior on VIEW with CHECK OPTION The "too many rows" check is done after the view's CHECK OPTION check. With UPDATE IGNORE, a row rejected by WITH CHECK OPTION is skipped (with a warning) and does not count as an updated row, so UPDATE IGNORE .. RETURNING .. INTO does not raise ER_TOO_MANY_ROWS if only one row is actually updated. Helper changes: 1. The grammar in analyze_stmt_command was changed to have LEX::analyze_stmt set to true earlier, so LEX::set_returning_into_result() already knows if this is an ANALYZE statement. 2. The Sql_cmd_update constructor is now called earlier in the grammar, to be able to call Sql_cmd_update::set_with_old_value_items() in the SET and RETURNING clauses. 3. Sql_cmd_dml::lex is now set during the constructor time. It makes things easier: - Sql_cmd_update::returns_result_set() needs the lex. - Sql_cmd_delete::orig_multitable and Sql_cmd_update::orig_multitable are not needed any more. They were used only in Sql_cmd_delete::sql_command_code() and Sql_cmd_update::sql_command_code(). Sql_cmd_dml::sql_command_code() now returns lex->sql_command. The overrides Sql_cmd_delete::sql_command_code() and Sql_cmd_update::sql_command_code() were removed. This commit also fixes bugs found during testing: - MDEV-41262 ER_TOO_MANY_ROWS should be checked after CHECK OPTION in view while Update Returning Into - MDEV-41265 SELECT/ UPDATE RETURNING INTO a single row-field fails with ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, even though the column count matches This bug was also fixed in 12.3.4. - MDEV-41260 Misleading message text "uses a LIMIT clause" after Update Returning Into - MDEV-42212 UPDATE ... RETURNING ... INTO raises ER_TOO_MANY_ROWS on InnoDB when the second found row needs no update |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
bsrikanth-mariadb
srikanth.bondalapati@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42044: Do the table privilege check once for trace and recorder Run opt_trace_disable_if_no_tables_access() once in mysql_execute_command(), after the recorder is created, instead of separately at trace start and in the recorder. Remove opt_ctx_can_read_all_columns(). The recorder now relies on its missing_priv flag and skips recording when it is set. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Petrunia
sergey@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42044: I_S.OPTIMIZER_CONTEXT exposes rows, DDL and statistics ... Optimizer Context has DDLs of used tables and VIEWs, table statistics, and even captured table rows which include all, even the columns that the query doesn't read. The user running the query might not have access to some of this information. Making it available in the optimizer context would create an opportunity to bypass the security controls. There is a similar issue in the Optimizer Trace. It is solved by not producing optimizer trace if it would expose data that's not available otherwise. Piggy-back on the Optimizer Trace security checks and do the same: disallow saving Optimizer Context if it can contain information that the caller would not have access to. In addition to Optimizer Trace's check, add opt_ctx_can_read_all_columns() and check that when we're about to dump a full table row into the optimizer context. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Elena Stepanova
elenst@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MDEV-42200 main.mysqlbinlog_stmt_compressed depends on previous tests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hemant Dangi
hemant.dangi@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41388: Avoid causal-wait timeout in galera.MDEV-34117 Issue: After re-enabling wsrep_on, the test's local session-variable checks (SET/SELECT @@wsrep_trx_fragment_unit/size) pay the suite's default causal-read wait (wsrep_sync_wait=15). On loaded/slow CI builders (aarch64-debian-12, s390x-ubuntu-2204) this occasionally exceeds the 90s causal_read_timeout and fails with ER_LOCK_WAIT_TIMEOUT, even though none of these checks depend on cross-node consistency. Solution: Disable wsrep_sync_wait for this narrow window of local-only checks, matching the existing on/off pattern used in galera_concurrent_test.inc and galera_mdev38999_cleanup.inc, and restore it before the later statements that do read data replicated from node_1. Assisted-by: Claude:claude-sonnet-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Marko Mäkelä
marko.makela@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Merge | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Mohammad Tafzeel Shams
tafzeel.shams@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-37467: InnoDB Instant ALTER TABLE is not crash safe The hidden metadata record of instant ALTER TABLE was not written crash-safely, and recovery could fail to roll it back. These are independent problems. First, the metadata record may include externally stored BLOB metadata. The existing BLOB storage path in btr_store_big_rec_extern_fields() writes the clustered index record first, with zero BLOB pointers, and only fills in the BLOB pointers afterwards. If the server is killed after the mini-transaction that wrote the (incomplete) metadata record was durably committed, but before the BLOB pointers were written, the table could become inaccessible on recovery. Make metadata BLOB storage crash-safe by writing the BLOB pages and computing their pointers before the metadata record itself is inserted or updated, so that the record is always written with complete BLOB pointers. If the server is killed before the metadata record is written, the already-written BLOB pages are merely orphaned, which is safe. Second, trx_undo_report_row_operation() writes the undo log record in a mini-transaction of its own, which is committed before the mini-transaction that writes the metadata record. Because innobase_instant_try() had already updated SYS_COLUMNS and SYS_TABLES in earlier mini-transactions, a kill in between left a durable undo log record for the table while the metadata record was unchanged. On recovery, trx_resurrect_table_locks() would then load the table definition before the incomplete transaction was rolled back. The data dictionary described the table as it would be after the operation, while the metadata record still described it as it was before, and btr_cur_instant_init() failed on that disagreement. Write the undo log record of the metadata record in the same mini-transaction that inserts or updates the record, so that the two cannot be separated by a crash: until that mini-transaction is committed, neither of them is durable. An undo log record is never split between pages. If the DEFAULT values of the columns being added are large enough that the undo log record for updating the metadata record would not fit on one page, innobase_instant_try() would fail. Determine this before the operation starts, so that it can be performed by another algorithm instead. Third, the table definition that recovery loads need not correspond to the metadata record. dict_load_table_one() reads the committed version of the SYS_TABLES record, and escalates to READ UNCOMMITTED only when it finds a SYS_COLUMNS record that was written by a transaction that is still active. The number of SYS_COLUMNS records that dict_load_columns() reads is derived from SYS_TABLES.N_COLS, which was read from the committed version. The record of a column that the operation appended is located after that many records, so it is never read and the operation goes unnoticed. Only an instant ALTER TABLE that merely appends columns can escape this way: ADD COLUMN ... FIRST, DROP COLUMN and column reordering rewrite the SYS_COLUMNS records of already existing columns. Load the committed table definition first, and the uncommitted one only if btr_cur_instant_init() reports that the committed definition does not describe the metadata record. Reading the uncommitted definition unconditionally would be wrong in the opposite case: if the operation had not updated the metadata record yet, the definition would describe columns that the record does not comprise, and btr_cur_instant_init() would request the default value of a column that does not have one. Fourth, the rollback writes a metadata record that comprises fewer fields than the table definition describes, because btr_cur_trim_alter_metadata() shortens it to the number of fields that it comprised before the operation. That number determines the size of the null flag bitmap, and hence the position of the array of field lengths. rec_init_offsets_comp_ordinary() derives it from the record, while the two functions that write the record derived it from the table definition and asserted that the two agree. - btr_store_big_rec_metadata(): New function to store the off-page columns of a metadata record ahead of time. Each BLOB page is allocated and linked in its own mini-transaction, and the resulting BLOB pointers are written directly into the (heap-resident) index entry. On failure, it frees any pages it already allocated and resets the pointers to zero. - btr_free_big_rec_metadata(): New helper to free the BLOB pages written by btr_store_big_rec_metadata() and reset the entry's BLOB pointers to zero, used both on failure inside that function and by its callers when the metadata record ends up not being written. - row_ins_clust_index_entry_low(): For a metadata entry that needs external storage, convert it to a big record and call btr_store_big_rec_metadata() (with log_free_check() allowed, since no latches are held yet) before inserting the record. On failure, free the metadata BLOBs and convert the entry back. - btr_cur_pessimistic_update(): When updating a metadata record that requires external storage, call btr_store_big_rec_metadata() (without log_free_check(), since index and page latches are held) before modifying the record, and free the temporary big_rec vector via btr_free_big_rec_metadata() or dtuple_big_rec_free() on the various failure/success paths. - btr_cur_optimistic_insert(): Remove the special-cased jump to convert_big_rec for metadata entries, since their BLOBs are now always stored ahead of time by the caller; assert that a metadata entry never needs external storage at this point. - innobase_instant_try(): Since btr_cur_pessimistic_update() now stores metadata BLOBs before updating the record, big_rec is always NULL here; assert this instead of calling btr_store_big_rec_extern_fields(). - trx_undo_report_row_operation(): New parameter caller_mtr. If it is specified, the undo log record is written in that mini-transaction, which is never committed or restarted here. An undo log page is added within the same mini-transaction if the record does not fit on the current one. A temporary table never uses the caller's mini-transaction, because that would require changing its logging mode. All other callers pass NULL and are unaffected. Encapsulate the parameters that describe the row change (clust_entry, update, cmpl_info, rec, offsets) in the new type trx_undo_row_op, which of the fields are set depends on the operation, which the type documents. - btr_cur_ins_lock_and_undo(), btr_cur_upd_lock_and_undo(): For an instant ALTER TABLE metadata record, pass the mini-transaction that is going to insert or modify the record. - trx_undo_max_rec_size(): New function to determine the maximum size of an undo log record, that is, the space available on an empty undo log page. - ha_innobase::check_if_supported_inplace_alter(): Refuse ALGORITHM=INSTANT if the metadata record already exists and the undo log record for updating it would exceed trx_undo_max_rec_size(). trx_undo_page_report_modify() stores the DEFAULT value of each column that is being added in that record in full, inline. No such limit applies when the metadata record is being inserted, because trx_undo_page_report_insert() writes TRX_UNDO_INSERT_METADATA and no field data. - dict_load_table_one(): Load the committed table definition first, and the uncommitted one only if btr_cur_instant_init() reports that the committed definition does not describe the clustered index metadata record. dict_load_columns() cannot detect this, because the number of SYS_COLUMNS records that it reads is derived from SYS_TABLES.N_COLS, and a column that the operation appended is located after that many records. A table that an uncommitted transaction is rebuilding is excluded, because the committed definition is the one that corresponds to its clustered index. - btr_cur_instant_init(), btr_cur_instant_init_low(): Determine the number of fields of the metadata record in the same way as rec_init_offsets_comp_ordinary() does, and refuse the table if it disagrees with the table definition. rec_get_offsets() would otherwise request the default value of a column that does not have one. New parameter quiet for a caller that is going to try another table definition, so that an attempt which is not the final one is not reported. Mark the table as unreadable on these failures, like the other ones in that function do, because dict_load_table_one() asserts that a readable table is not corrupted. - dict_sys_tables_rec_read(): Store the fields that are read in the new type dict_sys_tables_rec, instead of in separate output parameters. A caller that does not want a delete-marked record to be reported as not found used to indicate that by specifying trx_id as nullptr; that is now the parameter skip_deleted. - trx_undo_add_page(): Correct the documented restriction on the mini-transaction of the caller. - rec_get_converted_size_comp_prefix_low(), rec_convert_dtuple_to_rec_comp(): For a record that includes a metadata BLOB, determine the number of nullable fields from the tuple, by way of dict_index_t::get_n_nullable(), and not from dict_index_t::n_nullable. This is what rec_init_offsets_comp_ordinary() does, and it is equivalent for a tuple that comprises all fields of the index. Relax the assertions that required the tuple to comprise all of them. - Added test in innodb.instant_alter and innodb.instant_alter_crash to test normal working of INSTANT ALTER, crash safety and full table. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hemant Dangi
hemant.dangi@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41388: Avoid causal-wait timeout in galera.MDEV-34117 Issue: After re-enabling wsrep_on, the test's local session-variable checks (SET/SELECT @@wsrep_trx_fragment_unit/size) pay the suite's default causal-read wait (wsrep_sync_wait=15). On loaded/slow CI builders (aarch64-debian-12, s390x-ubuntu-2204) this occasionally exceeds the 90s causal_read_timeout and fails with ER_LOCK_WAIT_TIMEOUT, even though none of these checks depend on cross-node consistency. Solution: Disable wsrep_sync_wait for this narrow window of local-only checks, matching the existing on/off pattern used in galera_concurrent_test.inc and galera_mdev38999_cleanup.inc, and restore it before the later statements that do read data replicated from node_1. Assisted-by: Claude:claude-sonnet-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Elena Stepanova
elenst@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41085 Enable MTR tests on Windows: rpl suite rpl.rpl_read_old_relay_log_info fails because the test overrrides relay-log.info with the Linux-style ./slave-relay-bin.000001, while Windows uses the format with backslashes, .\slave-relay-bin.000001 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
bsrikanth-mariadb
srikanth.bondalapati@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42186: Info leak with optimizer_replay_context Replaying a context for a query on a view made the server push warnings naming the underlying tables, their indexes and the view's hidden range constants, even if the user could not read those tables. On the first use of the replay, check that the invoker can read all columns of every base table in the statement. If any table fails the check, drop the context, so nothing is replayed and no warnings are produced. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Jan Lindström
jan.lindstrom@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41996 galera.galera_change_user fails: extra change_user line The test calls change_user three times. The result file recorded the echoed "change_user user1,,;" line for the first two calls but not for the third one, added by MDEV-41385. The test output has the line after "# After COM_CHANGE_USER". Add the missing line to the result file. Assisted-by: Claude:claude-4.6-sonnet |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Alexander Barkov
bar@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-39563 Implement UPDATE ... RETURNING ... INTO Adding support for UPDATE .. RETURNING .. INTO queries. For example: UPDATE t1 SET a=10,b=20 RETURNING a,b INTO va,vb; UPDATE t1 SET a=10,b=20 RETURNING a,b INTO @a,@b; Limitations: 1. These types of queries: - REPLACE .. RETURNING .. INTO - DELETE .. RETURNING .. INTO - INSERT .. RETURNING .. INTO do not work - they return an error. They will be implemented separately, when needed. 2. UPDATE..RETURNING..INTO with --binlog_format=statement is not allowed and an error is raised. 3. Using OLD_VALUE(col) inside UPDATE..RETURNING..INTO is not allowed and an error is raised. 4. Multi-table updates, as well as single table updates with a subquery to the same table in WHERE (which get converted to multi-table) do not work and an error is raised. 5. UPDATE IGNORE .. RETURNING .. INTO is not supported for storage engines that can send updates later (Spider), because it is not known if the row was rejected. ER_NOT_SUPPORTED_YET is raised. Notes: 1. ANALYZE and EXPLAIN Both ANALYZE UPDATE .. RETURNING .. INTO .. EXPLAIN UPDATE .. RETURNING .. INTO .. return this error: 'RETURNING..INTO' is not allowed in this context 2. Behavior on no data and on multiple rows Only the rows that were actually changed are processed. A row that matches the WHERE condition but needs no update is not changed, so it is not returned by plain RETURNING either. Situation | RETURNING | RETURNING .. INTO -----------------------------+------------------+----------------------------- Empty table, WHERE matches | empty set | Warning ER_SP_FETCH_NO_DATA, nothing, WHERE 1=0, LIMIT 0 | | target is not changed One row matches, needs no | empty set | Warning ER_SP_FETCH_NO_DATA, update | | target is not changed Several rows match, none | empty set | Warning ER_SP_FETCH_NO_DATA, needs an update | | target is not changed | | (no ER_TOO_MANY_ROWS) One row matches and is | that row | Target is assigned changed | | Several rows match, exactly | that row | Target is assigned from one changes | | that row Two or more rows change | all changed rows | ER_TOO_MANY_ROWS at the 2nd | | changed row (not updated) Notes: - The warning is never an error: not in the strict mode, not with sql_mode='', not with IGNORE. The INTO targets keep their old values. In stored routines the warning activates NOT FOUND handlers. - This is the same for all storage engines, including those that quickly know the table is empty and use a degenerated plan (e.g. MyISAM). - After ER_TOO_MANY_ROWS, transactional engines roll back the statement, non-transactional engines keep the rows updated before the error (the second changed row is not updated). - The targets can be user variables, SP variables, ROW variables and ROW fields. 3. Behavior on VIEW with CHECK OPTION The "too many rows" check is done after the view's CHECK OPTION check. With UPDATE IGNORE, a row rejected by WITH CHECK OPTION is skipped (with a warning) and does not count as an updated row, so UPDATE IGNORE .. RETURNING .. INTO does not raise ER_TOO_MANY_ROWS if only one row is actually updated. 4. Behavior of UPDATE IGNORE .. RETURNING .. INTO With IGNORE, a row rejected by the storage engine (a duplicate key, no partition for the new values, a foreign key violation) is not changed, so it is not counted as a changed row, in the same way as for plain UPDATE IGNORE .. RETURNING. The engine decides about this in ha_update_row(), so the check for the second changed row is done after it: - Transactional engines: ER_TOO_MANY_ROWS rolls back the statement. - Non-transactional engines: the second row is updated back (including its BLOB values) before ER_TOO_MANY_ROWS is raised. Both updates are written to the binary log. Without IGNORE the check is done before the second row is updated. Helper changes: 1. The grammar in analyze_stmt_command was changed to have LEX::analyze_stmt set to true earlier, so LEX::set_returning_into_result() already knows if this is an ANALYZE statement. 2. The Sql_cmd_update constructor is now called earlier in the grammar, to be able to call Sql_cmd_update::set_with_old_value_items() in the SET and RETURNING clauses. 3. Sql_cmd_dml::lex is now set during the constructor time. It makes things easier: - Sql_cmd_update::returns_result_set() needs the lex. - Sql_cmd_delete::orig_multitable and Sql_cmd_update::orig_multitable are not needed any more. They were used only in Sql_cmd_delete::sql_command_code() and Sql_cmd_update::sql_command_code(). Sql_cmd_dml::sql_command_code() now returns lex->sql_command. The overrides Sql_cmd_delete::sql_command_code() and Sql_cmd_update::sql_command_code() were removed. 4. A new virtual method handler::update_may_be_deferred() tells if ha_update_row() can return success for a row that the engine rejects later. It is overridden in Spider and in ha_partition. This commit also fixes bugs found during testing: - MDEV-41262 ER_TOO_MANY_ROWS should be checked after CHECK OPTION in view while Update Returning Into - MDEV-41265 SELECT/ UPDATE RETURNING INTO a single row-field fails with ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, even though the column count matches This bug was also fixed in 12.3.4. - MDEV-41260 Misleading message text "uses a LIMIT clause" after Update Returning Into - MDEV-42212 UPDATE ... RETURNING ... INTO raises ER_TOO_MANY_ROWS on InnoDB when the second found row needs no update - MDEV-42156 UPDATE IGNORE ... RETURNING ... INTO fails with ER_TOO_MANY_ROWS when the second row is skipped by IGNORE (duplicate key) - MDEV-41448 Update Returning Into expected to produce warning/error for zero-row plan (a test was added; the warning is now raised consistently) - MDEV-41443 Update Returning into produces error when values don't change (a test was added; a warning is raised instead of an error) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
bsrikanth-mariadb
srikanth.bondalapati@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42186: Info leak with optimizer_replay_context Replaying a context for a query on a view made the server push warnings naming the underlying tables, their indexes and the view's hidden range constants, even if the user could not read those tables. On the first use of the replay, check that the invoker can read all columns of every base table in the statement. If any table fails the check, drop the context, so nothing is replayed and no warnings are produced. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sergei Petrunia
sergey@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Fixup: opt_ctx_can_read_all_columns() is not used for VIEWs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Marko Mäkelä
marko.makela@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
fixup! 7cfefd08e195bda8e03b0687632953656128ce7d InnoDB_backup::stream(): Correctly write the dummy blocks after DROP TABLE |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Oleksandr Byelkin
sanja@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41843 Forcing rotation of Aria log files Backup needs to switch Aria to a new log file so that the finished files can be copied without blocking commits. Added translog_rotate() and handlerton::rotate_logs (ha_rotate_logs()), implemented for Aria. Nothing in the server calls it yet (BACKUP SERVER will), so it is tested by the unit test ma_test_loghandler_rotate-t. Rotation of a log without records makes files with no records, which were not handled: - the header of such a file got max LSN 0, which purge takes for a file still in writing and never passes; now it gets the last address of the file - the scan for the first record (recovery without a checkpoint, aria_read_log) stopped at the filler of the empty file and found no records; now it goes on to the next page - the log start left a page of the empty log pinned Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Jan Lindström
jan.lindstrom@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42140 require galera >= 26.4.29 in galera_wsrep_schema_detached Add a galera library version check and the resulting .result line. Requires a galera library with the MDEV-42140 IST allowlist fix. Assisted-by: Claude:claude-4.6-sonnet |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Elena Stepanova
elenst@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42202 perfschema.relaylog fails when run after other replication tests The test checks file I/O instrumentation accumulated since server startup, so it relied on getting freshly started servers. With duplicate options removed, mtr may now reuse servers left by a previous replication test, and the test sees binary/relay log files and statistics from it. Restart both servers at the beginning of the test, removing binary and relay logs while the servers are down. RESET MASTER and RESET SLAVE are not sufficient, as performance schema keeps instances of files deleted by them, and a restart opens a new binary log anyway. Assisted-by: Claude:claude-opus-5-5 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Elena Stepanova
elenst@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-41085 Enable MTR tests on Windows: rpl suite rpl.rpl_change_master_long_channel_name fails on Windows because it expects a 252-character name (base name, excluding the path) to be valid; on Windows the whole path is limited to 260 characters, so 252-character name already fails |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Jan Lindström
jan.lindstrom@mariadb.com |
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
MDEV-42141 tolerate ER_NO_SUCH_TABLE in GCF-1018B's reap wsrep_sync_wait=0 lets node_2's DELETE run before node_1's CREATE TABLE replicates, so the first iteration of the test's 500-iteration INSERT/DELETE loop can legitimately race a not-yet-existing t1. The --error list on node_2's reap did not accept ER_NO_SUCH_TABLE, even though it already tolerates other non-deterministic races (lock wait, deadlock, duplicate key) for the same reason, matching the pattern used for the same race in GCF-1060 (MDEV-41923). |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||