This commit is contained in:
Jussi Saurio
2025-05-10 15:14:38 +03:00
parent 15b32f7e57
commit c18bb3cd14
3 changed files with 34 additions and 33 deletions

View File

@@ -106,8 +106,8 @@ pub fn find_best_access_method_for_join_order<'a>(
.columns()
.iter()
.position(|c| c.is_rowid_alias);
for usage in table_constraints.candidates.iter() {
let index_info = match usage.index.as_ref() {
for candidate in table_constraints.candidates.iter() {
let index_info = match candidate.index.as_ref() {
Some(index) => IndexInfo {
unique: index.unique,
covering: table_reference.index_is_covering(index),
@@ -121,7 +121,7 @@ pub fn find_best_access_method_for_join_order<'a>(
};
let usable_constraint_refs = usable_constraints_for_join_order(
&table_constraints.constraints,
&usage.refs,
&candidate.refs,
table_index,
join_order,
);
@@ -138,7 +138,7 @@ pub fn find_best_access_method_for_join_order<'a>(
for i in 0..order_target.0.len().min(index_info.column_count) {
let correct_table = order_target.0[i].table_no == table_index;
let correct_column = {
match &usage.index {
match &candidate.index {
Some(index) => index.columns[i].pos_in_table == order_target.0[i].column_no,
None => {
rowid_column_idx.map_or(false, |idx| idx == order_target.0[i].column_no)
@@ -151,7 +151,7 @@ pub fn find_best_access_method_for_join_order<'a>(
break;
}
let correct_order = {
match &usage.index {
match &candidate.index {
Some(index) => order_target.0[i].order == index.columns[i].order,
None => order_target.0[i].order == SortOrder::Asc,
}
@@ -172,7 +172,8 @@ pub fn find_best_access_method_for_join_order<'a>(
};
if cost < best_access_method.cost + order_satisfiability_bonus {
best_access_method.cost = cost;
best_access_method.set_constraint_refs(usage.index.clone(), &usable_constraint_refs);
best_access_method
.set_constraint_refs(candidate.index.clone(), &usable_constraint_refs);
}
}

View File

@@ -221,18 +221,18 @@ pub fn constraints_from_where_clause(
// For each constraint we found, add a reference to it for each index that may be able to use it.
for (i, constraint) in cs.constraints.iter().enumerate() {
if rowid_alias_column.map_or(false, |idx| constraint.table_col_pos == idx) {
let rowid_usage = cs
let rowid_candidate = cs
.candidates
.iter_mut()
.find_map(|usage| {
if usage.index.is_none() {
Some(usage)
.find_map(|candidate| {
if candidate.index.is_none() {
Some(candidate)
} else {
None
}
})
.unwrap();
rowid_usage.refs.push(ConstraintRef {
rowid_candidate.refs.push(ConstraintRef {
constraint_vec_pos: i,
index_col_pos: 0,
sort_order: SortOrder::Asc,
@@ -245,22 +245,22 @@ pub fn constraints_from_where_clause(
if let Some(position_in_index) =
index.column_table_pos_to_index_pos(constraint.table_col_pos)
{
let index_usage = cs
let index_candidate = cs
.candidates
.iter_mut()
.find_map(|usage| {
if usage
.find_map(|candidate| {
if candidate
.index
.as_ref()
.map_or(false, |i| Arc::ptr_eq(index, i))
{
Some(usage)
Some(candidate)
} else {
None
}
})
.unwrap();
index_usage.refs.push(ConstraintRef {
index_candidate.refs.push(ConstraintRef {
constraint_vec_pos: i,
index_col_pos: position_in_index,
sort_order: index.columns[position_in_index].order,
@@ -269,30 +269,30 @@ pub fn constraints_from_where_clause(
}
}
for usage in cs.candidates.iter_mut() {
for candidate in cs.candidates.iter_mut() {
// Deduplicate by position, keeping first occurrence (which will be equality if one exists, since the constraints vec is sorted that way)
usage.refs.dedup_by_key(|uref| uref.index_col_pos);
candidate.refs.dedup_by_key(|cref| cref.index_col_pos);
// Truncate at first gap in positions -- index columns must be consumed in contiguous order.
let mut last_pos = 0;
let mut i = 0;
for uref in usage.refs.iter() {
if uref.index_col_pos != last_pos {
if uref.index_col_pos != last_pos + 1 {
for cref in candidate.refs.iter() {
if cref.index_col_pos != last_pos {
if cref.index_col_pos != last_pos + 1 {
break;
}
last_pos = uref.index_col_pos;
last_pos = cref.index_col_pos;
}
i += 1;
}
usage.refs.truncate(i);
candidate.refs.truncate(i);
// Truncate after the first inequality, since the left-prefix rule of indexes requires that all constraints but the last one must be equalities;
// again see: https://www.solarwinds.com/blog/the-left-prefix-index-rule
if let Some(first_inequality) = usage.refs.iter().position(|uref| {
cs.constraints[uref.constraint_vec_pos].operator != ast::Operator::Equals
if let Some(first_inequality) = candidate.refs.iter().position(|cref| {
cs.constraints[cref.constraint_vec_pos].operator != ast::Operator::Equals
}) {
usage.refs.truncate(first_inequality + 1);
candidate.refs.truncate(first_inequality + 1);
}
}
constraints.push(cs);
@@ -312,8 +312,8 @@ pub fn usable_constraints_for_join_order<'a>(
join_order: &[JoinOrderMember],
) -> &'a [ConstraintRef] {
let mut usable_until = 0;
for uref in refs.iter() {
let constraint = &constraints[uref.constraint_vec_pos];
for cref in refs.iter() {
let constraint = &constraints[cref.constraint_vec_pos];
let other_side_refers_to_self = constraint.lhs_mask.contains_table(table_index);
if other_side_refers_to_self {
break;

View File

@@ -269,9 +269,9 @@ fn use_indexes(
iter_dir,
} => {
assert!(!constraint_refs.is_empty());
for uref in constraint_refs.iter() {
for cref in constraint_refs.iter() {
let constraint =
&constraints_per_table[table_number].constraints[uref.constraint_vec_pos];
&constraints_per_table[table_number].constraints[cref.constraint_vec_pos];
to_remove_from_where_clause.push(constraint.where_clause_pos.0);
}
if let Some(index) = index {
@@ -801,9 +801,9 @@ pub fn build_seek_def_from_constraints(
// Extract the key values and operators
let mut key = Vec::with_capacity(constraint_refs.len());
for uref in constraint_refs {
for cref in constraint_refs {
// Extract the other expression from the binary WhereTerm (i.e. the one being compared to the index column)
let constraint = &constraints[uref.constraint_vec_pos];
let constraint = &constraints[cref.constraint_vec_pos];
let (where_idx, side) = constraint.where_clause_pos;
let where_term = &where_clause[where_idx];
let ast::Expr::Binary(lhs, _, rhs) = unwrap_parens(where_term.expr.clone())? else {
@@ -814,7 +814,7 @@ pub fn build_seek_def_from_constraints(
} else {
*rhs
};
key.push((cmp_expr, uref.sort_order));
key.push((cmp_expr, cref.sort_order));
}
// We know all but potentially the last term is an equality, so we can use the operator of the last term