diff options
author | Sergei Petrunia <sergey@mariadb.com> | 2022-06-06 22:21:22 +0300 |
---|---|---|
committer | Sergei Petrunia <sergey@mariadb.com> | 2022-06-06 22:21:22 +0300 |
commit | 161e8c5b7132212d5884865e67c50657854f1b63 (patch) | |
tree | 56e87d77ade61d92d8246556434f99cea7a0ab5b /sql/sql_select.cc | |
parent | 2f8d0af8837392e7116f624729860615a33d2484 (diff) | |
download | mariadb-git-bb-10.6-mdev28749.tar.gz |
MDEV-28749: restore_prev_nj_state() doesn't update cur_sj_inner_tables correctlybb-10.6-mdev28749
Errors:
1. restore_prev_sj_state() assumed that
"we assume remaining_tables doesnt contain @tab"
which wasn't true.
2. Another bug in this function: it did remove bits from
join->cur_sj_inner_tables but never added them.
3. greedy_search() adds tables into the join prefix but
neglects to update the semi-join optimization state.
It does update nested outer join state, see this call:
check_interleaving_with_nj(best_table)
but there's no matching call to update the semi-join state.
(This wasn't visible because most of the state is in the POSITION
structure which is updated. But there is also state in JOIN, too)
The patch:
- Fixes all of the above
- Adds JOIN::dbug_verify_sj_inner_tables() which is used to verify the
state is correct at every step.
- Renamed advance_sj_state() to optimize_semi_joins().
= Introduced update_sj_state() which ideally should be called
"advance_sj_state" but I didn't reuse the name to avoid confusion.
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r-- | sql/sql_select.cc | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fa33f0e0500..ff5b0c5cae6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8663,6 +8663,10 @@ choose_plan(JOIN *join, table_map join_tables) { choose_initial_table_order(join); } + /* + Note: constant tables are already in the join prefix. We don't + put them into the cur_sj_inner_tables, though. + */ join->cur_sj_inner_tables= 0; if (straight_join) @@ -8976,8 +8980,8 @@ optimize_straight_join(JOIN *join, table_map join_tables) read_time+= COST_ADD(read_time - filter_cmp_gain, COST_ADD(position->read_time, record_count / TIME_FOR_COMPARE)); - advance_sj_state(join, join_tables, idx, &record_count, &read_time, - &loose_scan_pos); + optimize_semi_joins(join, join_tables, idx, &record_count, &read_time, + &loose_scan_pos); join_tables&= ~(s->table->map); double pushdown_cond_selectivity= 1.0; @@ -9157,6 +9161,12 @@ greedy_search(JOIN *join, /* This has been already checked by best_extension_by_limited_search */ DBUG_ASSERT(!is_interleave_error); + /* + Also, update the semi-join optimization state. Information about the + picked semi-join operation is in best_pos->...picker, but we need to + update the global state in the JOIN object, too. + */ + update_sj_state(join, best_table, idx, remaining_tables); /* find the position of 'best_table' in 'join->best_ref' */ best_idx= idx; @@ -9981,8 +9991,8 @@ best_extension_by_limited_search(JOIN *join, trace_one_table.add("rows_for_plan", current_record_count); trace_one_table.add("cost_for_plan", current_read_time); } - advance_sj_state(join, remaining_tables, idx, ¤t_record_count, - ¤t_read_time, &loose_scan_pos); + optimize_semi_joins(join, remaining_tables, idx, ¤t_record_count, + ¤t_read_time, &loose_scan_pos); /* Expand only partial plans with lower cost than the best QEP so far */ if (current_read_time >= join->best_read) |