Query planner should evaluate non boolean expressions ()

This commit is contained in:
Emmanuel Keller 2024-05-14 09:58:06 +01:00 committed by GitHub
parent 1c09e1863d
commit 6277aab0e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 97 additions and 8 deletions
core/src
idx/planner
syn/lexer
lib/tests

View file

@ -136,17 +136,26 @@ impl<'a> TreeBuilder<'a> {
| Value::Uuid(_)
| Value::Constant(_)
| Value::Geometry(_)
| Value::Datetime(_) => Ok(Node::Computed(Arc::new(v.to_owned()))),
| Value::Datetime(_)
| Value::Param(_)
| Value::Function(_) => Ok(Node::Computable),
Value::Array(a) => self.eval_array(stk, a).await,
Value::Subquery(s) => self.eval_subquery(stk, s).await,
Value::Param(p) => {
let v = stk.run(|stk| p.compute(stk, self.ctx, self.opt, self.txn, None)).await?;
stk.run(|stk| self.eval_value(stk, group, &v)).await
}
_ => Ok(Node::Unsupported(format!("Unsupported value: {}", v))),
}
}
async fn compute(&self, stk: &mut Stk, v: &Value, n: Node) -> Result<Node, Error> {
Ok(if n == Node::Computable {
match v.compute(stk, self.ctx, self.opt, self.txn, None).await {
Ok(v) => Node::Computed(Arc::new(v)),
Err(_) => Node::Unsupported(format!("Unsupported value: {}", v)),
}
} else {
n
})
}
async fn eval_array(&mut self, stk: &mut Stk, a: &Array) -> Result<Node, Error> {
let mut values = Vec::with_capacity(a.len());
for v in &a.0 {
@ -289,9 +298,15 @@ impl<'a> TreeBuilder<'a> {
if let Some(re) = self.resolved_expressions.get(e).cloned() {
return Ok(re.into());
}
let left = stk.run(|stk| self.eval_value(stk, group, l)).await?;
let right = stk.run(|stk| self.eval_value(stk, group, r)).await?;
// If both values are computable, then we can delegate the computation to the parent
if left == Node::Computable && right == Node::Computable {
return Ok(Node::Computable);
}
let exp = Arc::new(e.clone());
let left = Arc::new(stk.run(|stk| self.eval_value(stk, group, l)).await?);
let right = Arc::new(stk.run(|stk| self.eval_value(stk, group, r)).await?);
let left = Arc::new(self.compute(stk, l, left).await?);
let right = Arc::new(self.compute(stk, r, right).await?);
let mut io = None;
if let Some((id, local_irs, remote_irs)) = left.is_indexed_field() {
io = self.lookup_index_options(
@ -552,6 +567,7 @@ pub(super) enum Node {
IndexedField(Idiom, Vec<IndexRef>),
RecordField(Idiom, RecordOptions),
NonIndexedField(Idiom),
Computable,
Computed(Arc<Value>),
Unsupported(String),
}

View file

@ -15,7 +15,7 @@ pub enum Error {
InvalidRange,
#[error("expected uuid-strand to end")]
ExpectedStrandEnd,
#[error("missing a uuid seperator")]
#[error("missing a uuid separator")]
MissingSeperator,
}

View file

@ -2527,3 +2527,76 @@ async fn select_with_exact_operator() -> Result<(), Error> {
//
Ok(())
}
#[tokio::test]
async fn select_with_non_boolean_expression() -> Result<(), Error> {
let dbs = new_ds().await?;
let ses = Session::owner().with_ns("test").with_db("test");
//
let sql = "
DEFINE INDEX idx ON t FIELDS v;
CREATE t:1 set v = 1;
CREATE t:2 set v = 2;
LET $p1 = 1;
LET $p3 = 3;
SELECT * FROM t WHERE v > math::max([0, 1]);
SELECT * FROM t WHERE v > math::max([0, 1]) EXPLAIN;
SELECT * FROM t WHERE v > 3 - math::max([0, 2]);
SELECT * FROM t WHERE v > 3 - math::max([0, 2]) EXPLAIN;
SELECT * FROM t WHERE v > 3 - math::max([0, 1]) - 1;
SELECT * FROM t WHERE v > 3 - math::max([0, 1]) - 1 EXPLAIN;
SELECT * FROM t WHERE v > 3 - ( math::max([0, 1]) + 1 );
SELECT * FROM t WHERE v > 3 - ( math::max([0, 1]) + 1 ) EXPLAIN;
SELECT * FROM t WHERE v > $p3 - ( math::max([0, $p1]) + $p1 );
SELECT * FROM t WHERE v > $p3 - ( math::max([0, $p1]) + $p1 ) EXPLAIN;
";
let mut res = dbs.execute(&sql, &ses, None).await?;
//
assert_eq!(res.len(), 15);
skip_ok(&mut res, 5)?;
//
for i in 0..5 {
let tmp = res.remove(0).result?;
let val = Value::parse(
r#"[
{
id: t:2,
v: 2
}
]"#,
);
assert_eq!(format!("{:#}", tmp), format!("{:#}", val), "{i}");
//
let tmp = res.remove(0).result?;
let val = Value::parse(
r#"[
{
detail: {
plan: {
from: {
inclusive: false,
value: 1
},
index: 'idx',
to: {
inclusive: false,
value: NONE
}
},
table: 't'
},
operation: 'Iterate Index'
},
{
detail: {
type: 'Memory'
},
operation: 'Collector'
}
]"#,
);
assert_eq!(format!("{:#}", tmp), format!("{:#}", val), "{i}");
}
//
Ok(())
}