From 1b73d3e4e4cf460dec2256bc3c40fd87e407adc1 Mon Sep 17 00:00:00 2001 From: Emmanuel Keller Date: Fri, 30 Jun 2023 17:51:03 +0100 Subject: [PATCH] feat: the query planner should support params (#2200) --- lib/src/idx/planner/mod.rs | 7 +++---- lib/src/idx/planner/tree.rs | 8 ++++++++ lib/src/sql/statements/select.rs | 2 +- lib/tests/matches.rs | 7 ++++--- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/src/idx/planner/mod.rs b/lib/src/idx/planner/mod.rs index 0f50b13b..e0d9b21d 100644 --- a/lib/src/idx/planner/mod.rs +++ b/lib/src/idx/planner/mod.rs @@ -30,18 +30,17 @@ impl<'a> QueryPlanner<'a> { pub(crate) async fn get_iterable( &mut self, ctx: &Context<'_>, - opt: &Options, t: Table, ) -> Result { let txn = ctx.try_clone_transaction()?; - let res = Tree::build(self.opt, &txn, &t, self.cond).await?; + let res = Tree::build(ctx, self.opt, &txn, &t, self.cond).await?; if let Some((node, im)) = res { if let Some(plan) = AllAndStrategy::build(&node)? { - let e = QueryExecutor::new(opt, &txn, &t, im, Some(plan.e.clone())).await?; + let e = QueryExecutor::new(self.opt, &txn, &t, im, Some(plan.e.clone())).await?; self.executors.insert(t.0.clone(), e); return Ok(Iterable::Index(t, plan)); } - let e = QueryExecutor::new(opt, &txn, &t, im, None).await?; + let e = QueryExecutor::new(self.opt, &txn, &t, im, None).await?; self.executors.insert(t.0.clone(), e); } Ok(Iterable::Table(t)) diff --git a/lib/src/idx/planner/tree.rs b/lib/src/idx/planner/tree.rs index 533aa374..51846b33 100644 --- a/lib/src/idx/planner/tree.rs +++ b/lib/src/idx/planner/tree.rs @@ -1,3 +1,4 @@ +use crate::ctx::Context; use crate::dbs::{Options, Transaction}; use crate::err::Error; use crate::idx::planner::plan::IndexOption; @@ -14,12 +15,14 @@ impl Tree { /// Traverse the all the conditions and extract every expression /// that can be resolved by an index. pub(super) async fn build<'a>( + ctx: &'a Context<'_>, opt: &'a Options, txn: &'a Transaction, table: &'a Table, cond: &Option, ) -> Result, Error> { let mut b = TreeBuilder { + ctx, opt, txn, table, @@ -35,6 +38,7 @@ impl Tree { } struct TreeBuilder<'a> { + ctx: &'a Context<'a>, opt: &'a Options, txn: &'a Transaction, table: &'a Table, @@ -74,6 +78,10 @@ impl<'a> TreeBuilder<'a> { Value::Number(_) => Node::Scalar(v.to_owned()), Value::Bool(_) => Node::Scalar(v.to_owned()), Value::Subquery(s) => self.eval_subquery(s).await?, + Value::Param(p) => { + let v = p.compute(self.ctx, self.opt).await?; + self.eval_value(&v).await? + } _ => Node::Unsupported, }) } diff --git a/lib/src/sql/statements/select.rs b/lib/src/sql/statements/select.rs index 377dc315..3d839d93 100644 --- a/lib/src/sql/statements/select.rs +++ b/lib/src/sql/statements/select.rs @@ -89,7 +89,7 @@ impl SelectStatement { let v = w.compute(ctx, opt).await?; match v { Value::Table(t) => { - i.ingest(planner.get_iterable(ctx, opt, t).await?); + i.ingest(planner.get_iterable(ctx, t).await?); } Value::Thing(v) => i.ingest(Iterable::Thing(v)), Value::Range(v) => i.ingest(Iterable::Range(*v)), diff --git a/lib/tests/matches.rs b/lib/tests/matches.rs index 3b16b3f9..1896d35e 100644 --- a/lib/tests/matches.rs +++ b/lib/tests/matches.rs @@ -234,15 +234,16 @@ async fn select_where_matches_without_using_index_and_score() -> Result<(), Erro CREATE blog:4 SET title = 'the dog sat there and did nothing'; DEFINE ANALYZER simple TOKENIZERS blank,class; DEFINE INDEX blog_title ON blog FIELDS title SEARCH ANALYZER simple BM25 HIGHLIGHTS; - SELECT id,search::score(1) AS score FROM blog WHERE (title @1@ 'animals' AND id>0) OR (title @1@ 'animals' AND id<99); + LET $keywords = 'animals'; + SELECT id,search::score(1) AS score FROM blog WHERE (title @1@ $keywords AND id>0) OR (title @1@ $keywords AND id<99); SELECT id,search::score(1) + search::score(2) AS score FROM blog WHERE title @1@ 'dummy1' OR title @2@ 'dummy2'; "; let dbs = Datastore::new("memory").await?; let ses = Session::for_kv().with_ns("test").with_db("test"); let res = &mut dbs.execute(&sql, &ses, None, false).await?; - assert_eq!(res.len(), 8); + assert_eq!(res.len(), 9); // - for _ in 0..6 { + for _ in 0..7 { let _ = res.remove(0).result?; }