mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-30 22:44:21 +01:00
Merge 'Fix incorrectly using an equality constraint twice for index seek' from Jussi Saurio
Prevents something like `WHERE x = 5 AND x = 5` from becoming a two component index key. Closes #3656 Reviewed-by: Nikita Sivukhin (@sivukhin) Closes #3658
This commit is contained in:
@@ -486,7 +486,7 @@ pub fn usable_constraints_for_join_order<'a>(
|
||||
.map(|j| j.original_idx),
|
||||
);
|
||||
let mut usable: Vec<RangeConstraintRef> = Vec::new();
|
||||
let mut last_column_pos = 0;
|
||||
let mut current_required_column_pos = 0;
|
||||
for cref in refs.iter() {
|
||||
let constraint = &constraints[cref.constraint_vec_pos];
|
||||
let other_side_refers_to_self = constraint.lhs_mask.contains_table(table_idx);
|
||||
@@ -498,6 +498,7 @@ pub fn usable_constraints_for_join_order<'a>(
|
||||
break;
|
||||
}
|
||||
if Some(cref.index_col_pos) == usable.last().map(|x| x.index_col_pos) {
|
||||
// Two constraints on the same index column can be combined into a single range constraint.
|
||||
assert_eq!(cref.sort_order, usable.last().unwrap().sort_order);
|
||||
assert_eq!(cref.index_col_pos, usable.last().unwrap().index_col_pos);
|
||||
assert_eq!(
|
||||
@@ -520,15 +521,28 @@ pub fn usable_constraints_for_join_order<'a>(
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if cref.index_col_pos != last_column_pos {
|
||||
if cref.index_col_pos != current_required_column_pos {
|
||||
// Index columns must be consumed contiguously in the order they appear in the index.
|
||||
break;
|
||||
}
|
||||
if usable.last().is_some_and(|x| x.eq.is_none()) {
|
||||
// Usable index key must have 0-n equalities and then a maximum of 1 range constraint with one or both bounds set.
|
||||
// If we already have a range constraint before this one, we must not add anything to it
|
||||
break;
|
||||
}
|
||||
let constraint_group = match constraints[cref.constraint_vec_pos].operator {
|
||||
let operator = constraints[cref.constraint_vec_pos].operator;
|
||||
let table_col_pos = constraints[cref.constraint_vec_pos].table_col_pos;
|
||||
if operator == ast::Operator::Equals
|
||||
&& usable
|
||||
.last()
|
||||
.is_some_and(|x| x.table_col_pos == table_col_pos)
|
||||
{
|
||||
// If we already have an equality constraint for this column, we can't use it again
|
||||
continue;
|
||||
}
|
||||
let constraint_group = match operator {
|
||||
ast::Operator::Equals => RangeConstraintRef {
|
||||
table_col_pos: constraints[cref.constraint_vec_pos].table_col_pos,
|
||||
table_col_pos,
|
||||
index_col_pos: cref.index_col_pos,
|
||||
sort_order: cref.sort_order,
|
||||
eq: Some(cref.constraint_vec_pos),
|
||||
@@ -536,7 +550,7 @@ pub fn usable_constraints_for_join_order<'a>(
|
||||
upper_bound: None,
|
||||
},
|
||||
ast::Operator::Greater | ast::Operator::GreaterEquals => RangeConstraintRef {
|
||||
table_col_pos: constraints[cref.constraint_vec_pos].table_col_pos,
|
||||
table_col_pos,
|
||||
index_col_pos: cref.index_col_pos,
|
||||
sort_order: cref.sort_order,
|
||||
eq: None,
|
||||
@@ -544,7 +558,7 @@ pub fn usable_constraints_for_join_order<'a>(
|
||||
upper_bound: None,
|
||||
},
|
||||
ast::Operator::Less | ast::Operator::LessEquals => RangeConstraintRef {
|
||||
table_col_pos: constraints[cref.constraint_vec_pos].table_col_pos,
|
||||
table_col_pos,
|
||||
index_col_pos: cref.index_col_pos,
|
||||
sort_order: cref.sort_order,
|
||||
eq: None,
|
||||
@@ -554,7 +568,7 @@ pub fn usable_constraints_for_join_order<'a>(
|
||||
_ => continue,
|
||||
};
|
||||
usable.push(constraint_group);
|
||||
last_column_pos += 1;
|
||||
current_required_column_pos += 1;
|
||||
}
|
||||
usable
|
||||
}
|
||||
|
||||
@@ -384,3 +384,10 @@ do_execsql_test_on_specific_db {:memory:} left-join-using-null {
|
||||
select a, b from t left join s using (a, b);
|
||||
} {1|
|
||||
2|}
|
||||
|
||||
# Regression test for: https://github.com/tursodatabase/turso/issues/3656
|
||||
do_execsql_test_on_specific_db {:memory:} redundant-join-condition {
|
||||
create table t(x);
|
||||
insert into t values ('lol');
|
||||
select t1.x from t t1 join t t2 on t1.x=t2.x where t1.x=t2.x;
|
||||
} {lol}
|
||||
Reference in New Issue
Block a user