summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
authorSergei Petrunia <sergey@mariadb.com>2022-06-06 22:21:22 +0300
committerSergei Petrunia <sergey@mariadb.com>2022-06-06 22:21:22 +0300
commit161e8c5b7132212d5884865e67c50657854f1b63 (patch)
tree56e87d77ade61d92d8246556434f99cea7a0ab5b /sql/sql_select.cc
parent2f8d0af8837392e7116f624729860615a33d2484 (diff)
downloadmariadb-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.cc18
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, &current_record_count,
- &current_read_time, &loose_scan_pos);
+ optimize_semi_joins(join, remaining_tables, idx, &current_record_count,
+ &current_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)