Fixes 3990 ()

This commit is contained in:
Emmanuel Keller 2024-05-10 11:46:10 +01:00 committed by GitHub
parent 24ae06051e
commit fcaff735e6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 111 additions and 3 deletions
core/src/idx/planner
lib/tests

View file

@ -332,9 +332,15 @@ impl QueryExecutor {
io: IndexOption,
) -> Result<Option<ThingIterator>, Error> {
Ok(match io.op() {
IndexOperator::Equality(value) => Some(ThingIterator::IndexEqual(
IndexEqualThingIterator::new(opt.ns(), opt.db(), &ix.what, &ix.name, value),
)),
IndexOperator::Equality(value) | IndexOperator::Exactness(value) => {
Some(ThingIterator::IndexEqual(IndexEqualThingIterator::new(
opt.ns(),
opt.db(),
&ix.what,
&ix.name,
value,
)))
}
IndexOperator::Union(value) => Some(ThingIterator::IndexUnion(
IndexUnionThingIterator::new(opt.ns(), opt.db(), &ix.what, &ix.name, value),
)),

View file

@ -175,6 +175,7 @@ pub(super) struct IndexOption {
#[derive(Debug, Eq, PartialEq, Hash)]
pub(super) enum IndexOperator {
Equality(Value),
Exactness(Value),
Union(Array),
Join(Vec<IndexOption>),
RangePart(Operator, Value),
@ -232,6 +233,10 @@ impl IndexOption {
e.insert("operator", Value::from(Operator::Equal.to_string()));
e.insert("value", Self::reduce_array(v));
}
IndexOperator::Exactness(v) => {
e.insert("operator", Value::from(Operator::Exact.to_string()));
e.insert("value", Self::reduce_array(v));
}
IndexOperator::Union(a) => {
e.insert("operator", Value::from("union"));
e.insert("value", Value::Array(a.clone()));

View file

@ -477,6 +477,7 @@ impl<'a> TreeBuilder<'a> {
if let Some(v) = n.is_computed() {
match (op, v, p) {
(Operator::Equal, v, _) => Some(IndexOperator::Equality(v.clone())),
(Operator::Exact, v, _) => Some(IndexOperator::Exactness(v.clone())),
(Operator::Contain, v, IdiomPosition::Left) => {
Some(IndexOperator::Equality(v.clone()))
}

View file

@ -2431,3 +2431,99 @@ async fn select_with_record_id_index() -> Result<(), Error> {
assert_eq!(format!("{:#}", tmp), format!("{:#}", val));
Ok(())
}
#[tokio::test]
async fn select_with_exact_operator() -> Result<(), Error> {
let dbs = new_ds().await?;
let ses = Session::owner().with_ns("test").with_db("test");
//
let sql = "
DEFINE INDEX idx ON TABLE t COLUMNS b;
DEFINE INDEX uniq ON TABLE t COLUMNS i;
CREATE t:1 set b = true, i = 1;
CREATE t:2 set b = false, i = 2;
SELECT * FROM t WHERE b == true;
SELECT * FROM t WHERE b == true EXPLAIN;
SELECT * FROM t WHERE i == 2;
SELECT * FROM t WHERE i == 2 EXPLAIN;
";
let mut res = dbs.execute(&sql, &ses, None).await?;
//
assert_eq!(res.len(), 8);
skip_ok(&mut res, 4)?;
//
let tmp = res.remove(0).result?;
let val = Value::parse(
r#"[
{
b: true,
i: 1,
id: t:1
}
]"#,
);
assert_eq!(format!("{:#}", tmp), format!("{:#}", val));
//
let tmp = res.remove(0).result?;
let val = Value::parse(
r#"[
{
detail: {
plan: {
index: 'idx',
operator: '==',
value: true
},
table: 't'
},
operation: 'Iterate Index'
},
{
detail: {
type: 'Memory'
},
operation: 'Collector'
}
]"#,
);
assert_eq!(format!("{:#}", tmp), format!("{:#}", val));
//
//
let tmp = res.remove(0).result?;
let val = Value::parse(
r#"[
{
b: false,
i: 2,
id: t:2
}
]"#,
);
assert_eq!(format!("{:#}", tmp), format!("{:#}", val));
//
let tmp = res.remove(0).result?;
let val = Value::parse(
r#"[
{
detail: {
plan: {
index: 'uniq',
operator: '==',
value: 2
},
table: 't'
},
operation: 'Iterate Index'
},
{
detail: {
type: 'Memory'
},
operation: 'Collector'
}
]"#,
);
assert_eq!(format!("{:#}", tmp), format!("{:#}", val));
//
Ok(())
}