Skip to content

Commit

Permalink
fix: the problem of incorrect ConstantBinary::and_scope_aggregation
Browse files Browse the repository at this point in the history
… when `And` exists in `Or` and Ignore `ConstantBinary::Scope` whose lower bound is larger than the upper bound and When the same NotEq and Eq exist in or, convert to Unbound
  • Loading branch information
KKould committed Mar 2, 2024
1 parent 2c2d46c commit 4d1dbf8
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[package]
name = "fnck_sql"
version = "0.0.1-alpha.11.fix1"
version = "0.0.1-alpha.11.fix2"
edition = "2021"
authors = ["Kould <[email protected]>", "Xwg <[email protected]>"]
description = "Fast Insert OLTP SQL DBMS"
Expand Down
3 changes: 1 addition & 2 deletions src/binder/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,7 @@ impl<'a, T: Transaction> Binder<'a, T> {
let scan_op = ScanOperator::build(table_name.clone(), table_catalog);

if let Some(TableAlias { name, columns }) = alias {
let alias = lower_ident(name);
self.register_alias(columns, alias.clone(), table_name.clone())?;
self.register_alias(columns, lower_ident(name), table_name.clone())?;
}

Ok(scan_op)
Expand Down
47 changes: 34 additions & 13 deletions src/expression/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,16 @@ impl ConstantBinary {
// `Or` is allowed to contain And, `Scope`, `Eq/NotEq`
// Tips: Only single-level `And`
ConstantBinary::Or(binaries) => {
for binary in binaries.iter_mut() {
for binary in mem::take(binaries) {
match binary {
ConstantBinary::And(and_binaries) => {
Self::and_scope_aggregation(and_binaries)?
ConstantBinary::And(mut and_binaries) => {
Self::and_scope_aggregation(&mut and_binaries)?;
binaries.append(&mut and_binaries);
}
ConstantBinary::Or(_) => {
unreachable!("`Or` does not allow nested `Or`")
}
_ => (),
binary => binaries.push(binary),
}
}
Self::or_scope_aggregation(binaries);
Expand Down Expand Up @@ -244,14 +245,17 @@ impl ConstantBinary {

// when there are multiple inconsistent eq conditions for the same field in And,
// then no row can meet the conditions.
// e.g. `select * from t1 where c1 = 0 and c1 =1` no data can be both 0 and 1 at the same time
// e.g. `select * from t1 where c1 = 0 and c1 = 1` no data can be both 0 and 1 at the same time
if eq_set.len() > 1 {
binaries.clear();
return Ok(());
}
}
ConstantBinary::NotEq(val) => {
let _ = eq_set.remove(val);
if eq_set.contains(val) {
binaries.clear();
return Ok(());
}
}
ConstantBinary::Or(_) | ConstantBinary::And(_) => {
return Err(DatabaseError::InvalidType)
Expand All @@ -268,10 +272,17 @@ impl ConstantBinary {
(&scope_min, &scope_max),
(Bound::Unbounded, Bound::Unbounded)
) {
binaries.push(ConstantBinary::Scope {
min: scope_min,
max: scope_max,
});
// When there is something like `select * from t1 where c1 between 1 and null`,
// None will be returned
if matches!(
Self::bound_compared(&scope_min, &scope_max, true).map(Ordering::is_le),
Some(true)
) {
binaries.push(ConstantBinary::Scope {
min: scope_min,
max: scope_max,
});
}
} else if eq_set.is_empty() {
binaries.push(ConstantBinary::Scope {
min: Bound::Unbounded,
Expand All @@ -288,11 +299,16 @@ impl ConstantBinary {
return;
}
let mut scopes = Vec::new();
let mut eqs = Vec::new();
let mut eqs = HashSet::new();

let mut scope_margin = None;

for binary in binaries.iter_mut() {
let sort_op = |binary: &&mut ConstantBinary| match binary {
ConstantBinary::NotEq(_) => 2,
ConstantBinary::Eq(_) => 1,
_ => 3,
};
for binary in binaries.iter_mut().sorted_by_key(sort_op) {
if matches!(scope_margin, Some((Bound::Unbounded, Bound::Unbounded))) {
break;
}
Expand Down Expand Up @@ -324,7 +340,12 @@ impl ConstantBinary {

scopes.push((min, max))
}
ConstantBinary::Eq(val) => eqs.push(val.clone()),
ConstantBinary::Eq(val) => {
let _ = eqs.insert(val.clone());
}
ConstantBinary::NotEq(val) => {
let _ = eqs.remove(val);
}
_ => (),
}
}
Expand Down
18 changes: 18 additions & 0 deletions tests/slt/where_by_index.slt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ query IIT
select * from t1 where id = 0 and id = 1;
----

query IIT
select * from t1 where id = 0 and id != 0;
----

query IIT
select * from t1 where id = 0 or id != 0 limit 10;
----
0 1 2
3 4 5
6 7 8
9 10 11
12 13 14
15 16 17
18 19 20
21 22 23
24 25 26
27 28 29

query IIT
select * from t1 where id = 0 and id != 0 and id = 3;
----
Expand Down

0 comments on commit 4d1dbf8

Please sign in to comment.