[MDEV-30975] Wrong result with cross Join given join order Created: 2023-03-31 Updated: 2024-01-15 |
|
| Status: | In Review |
| Project: | MariaDB Server |
| Component/s: | Optimizer |
| Affects Version/s: | 10.11.2, 10.3.38, 10.4.28, 10.6.12 |
| Fix Version/s: | 10.4 |
| Type: | Bug | Priority: | Critical |
| Reporter: | NAMHEE KIM | Assignee: | Sergei Petrunia |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | wrong_result | ||
| Environment: |
CentOS 7.9, MariaDB 10.3 ~ 10.11 |
||
| Description |
|
STRAIGHT_JOIN:
|
| Comments |
| Comment by Alice Sherepa [ 2023-04-03 ] | ||||||||||||||||||||||
|
Thank you for the report! I repeated as described on 10.4-10.11, Myisam/InnoDB:
| ||||||||||||||||||||||
| Comment by Dave Gosselin [ 2024-01-11 ] | ||||||||||||||||||||||
|
Any line number references below are with respect to 10.4 at git sha 88c46aba753c00. The apparent root of this issue is that we attempt to fill a derived table more than once, but without clearing its rows, so it consequently has duplicate rows. It doesn't matter if we enable join cache or not, or if we enable condition pushdown for derived optimization or not; the results are the same. The queries on this ticket may be simplified to "SELECT STRAIGHT_JOIN c1 FROM t1 JOIN (SELECT @a := 0) x;" to observe the result of this problem. This query has a derived table for "(SELECT @a := 0) x" which is backed by a temporary table and populated during mysql_derived_fill. The fact that this derived table sets a session variable causes us to mark the corresponding LEX as UNCACHEABLE_SIDEEFFECT. This is important later. Below I've included two stack traces from the execution of "SELECT STRAIGHT_JOIN c1 FROM t1 JOIN (SELECT @a := 0) x;" to show that we enter mysql_derived_fill twice (for simplicity of stack traces, both join cache and pushdown condition are disabled). During the "First Time", unit->executed is false and unit->uncacheable is 4 (sideeffect) and all is OK: we populate the derived table. But during the "Second Time", unit->executed is true and unit->uncacheable is still 4, so we again populate the table. During today's SQL Processor call meeting, we discussed several possible fixes. Since mysql_derived_fill will, for UNCACHEABLE_DEPENDENT tables, drop all rows and repopulate, we thought it reasonable to relax the condition at line 1204. Rather than !unit->uncacheable, we consider !(unit->uncacheable & UNCACHEABLE_DEPENDENT) to be more correct because we only populate derived tables once unless they're dependent tables (subquery has fields from outer query). Indeed such a change passes all of our mtr tests, but would like an opinion from igor First Time Second Time | ||||||||||||||||||||||
| Comment by Igor Babaev [ 2024-01-11 ] | ||||||||||||||||||||||
|
Gosselin: yes, your suggested change would be appropriate. | ||||||||||||||||||||||
| Comment by Dave Gosselin [ 2024-01-11 ] | ||||||||||||||||||||||