[MDEV-25576] The statement EXPLAIN running as regular statement and as prepared statement produces different results for UPDATE with subquery Created: 2021-05-01 Updated: 2021-06-17 Resolved: 2021-05-30 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Prepared Statements |
| Affects Version/s: | 10.2, 10.3, 10.4, 10.5, 10.6 |
| Fix Version/s: | 10.6.2, 10.2.39, 10.3.30, 10.4.20, 10.5.11 |
| Type: | Bug | Priority: | Major |
| Reporter: | Dmitry Shulga | Assignee: | Dmitry Shulga |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | None | ||
| Issue Links: |
|
||||||||||||
| Description |
|
Both EXPLAIN and EXPLAIN EXTENDED produce different results set in case it is run in normal way and in PS mode for the statement UPDATE with subquery.
Different results are also produced by the statement 'DELETE FROM with subquery' in case it is run in normal way and in PS mode.
|
| Comments |
| Comment by Oleksandr Byelkin [ 2021-05-19 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
fix to ex->all_selects_list and ok to push | ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2021-05-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
Some general background. Reading the code, one can see two kinds of JOIN optimization: 1. Optimization with intent to execute the JOIN Which kind of optimization is done is governed by (join->select_options & SELECT_DESCRIBE). Note that also there is (select_lex->options & SELECT_DESCRIBE). I am not sure if these two are equivalent (seems so). ( A question: We have a feature where "cheap" subqueries can be evaluated at the optimization phase. But before we know if the subquery is cheap, we need to optimize it... When we are optimizing it, should we use SELECT_DESCRIBE flag or not? | ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2021-05-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||
Prepared statement variantmysql_update calls st_select_lex::optimize_unflattened_subqueries which calls Execution hits these lines:
We have:
which is not entirely correct (this is EXPLAIN statement and we will never execute this query even as "cheap-to-compute subselect") Non-prepared-statement caseThe subquery is invoked with
The above if-branch is not taken. We proceed a bit further in the query (I don't see much value in what is executed) until these lines:
...then into make_join_select() which computes the Item_int and returns 1:
| ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2021-05-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
I don't see any reason why this should be fixed in a non-development version. This behavior does not cause any problems. | ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2021-05-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
I've tried to investigate what's the point of having this check for SELECT_DESCRIBE:
I don't see any reason for having this. The check itself is very ancient, it was there in the "Import changeset" in 2000. | ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2021-05-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
I would suggest this patch:
It causes A LOT of differences in EXPLAIN output, though.
And the cause is as described in the above comments: when there is a const table where we couldn't find the row, the execution doesn't leave with zero_result_cause= "no matching row in const table". Instead, it proceeds further where the WHERE clause is changed into Item_int(0). Then, make_join_select() computes it and sets "Impossible where" status. | ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2021-05-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
The second most popular difference is
which I don't find meaningful | ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2021-05-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
This piece looks like some hack:
It was introduced by https://github.com/mariadb/server/commit/8762539d477d949a5bd4c2df8b03b28727e5ee98. | ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2021-05-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
There are two approaches to addressing the issue (= making the EXPLAIN output the same): A. Unify PS and non-PS execution paths: make sure they both either pass or don't pass the SELECT_DESCRIBE flag when invoking child select's JOIN::optimize B. Make JOIN::optimize produce the same output regardless of whether SELECT_DESCRIBE flag is set. My comments above have been mostly about B. | ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2021-05-28 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
This patch fixes the test failures in bb-10.2-
| ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Dmitry Shulga [ 2021-05-30 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
For 10.4 and upper the following changeset should applied instead the original one from commit.
| ||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Sergei Petrunia [ 2021-06-02 ] | ||||||||||||||||||||||||||||||||||||||||||||||
|
Input from the last optimizer call:
|