feat: the query planner should support params (#2200)

This commit is contained in:
Emmanuel Keller 2023-06-30 17:51:03 +01:00 committed by GitHub
parent 699880f155
commit 1b73d3e4e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 16 additions and 8 deletions

View file

@ -30,18 +30,17 @@ impl<'a> QueryPlanner<'a> {
pub(crate) async fn get_iterable( pub(crate) async fn get_iterable(
&mut self, &mut self,
ctx: &Context<'_>, ctx: &Context<'_>,
opt: &Options,
t: Table, t: Table,
) -> Result<Iterable, Error> { ) -> Result<Iterable, Error> {
let txn = ctx.try_clone_transaction()?; 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((node, im)) = res {
if let Some(plan) = AllAndStrategy::build(&node)? { 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); self.executors.insert(t.0.clone(), e);
return Ok(Iterable::Index(t, plan)); 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); self.executors.insert(t.0.clone(), e);
} }
Ok(Iterable::Table(t)) Ok(Iterable::Table(t))

View file

@ -1,3 +1,4 @@
use crate::ctx::Context;
use crate::dbs::{Options, Transaction}; use crate::dbs::{Options, Transaction};
use crate::err::Error; use crate::err::Error;
use crate::idx::planner::plan::IndexOption; use crate::idx::planner::plan::IndexOption;
@ -14,12 +15,14 @@ impl Tree {
/// Traverse the all the conditions and extract every expression /// Traverse the all the conditions and extract every expression
/// that can be resolved by an index. /// that can be resolved by an index.
pub(super) async fn build<'a>( pub(super) async fn build<'a>(
ctx: &'a Context<'_>,
opt: &'a Options, opt: &'a Options,
txn: &'a Transaction, txn: &'a Transaction,
table: &'a Table, table: &'a Table,
cond: &Option<Cond>, cond: &Option<Cond>,
) -> Result<Option<(Node, IndexMap)>, Error> { ) -> Result<Option<(Node, IndexMap)>, Error> {
let mut b = TreeBuilder { let mut b = TreeBuilder {
ctx,
opt, opt,
txn, txn,
table, table,
@ -35,6 +38,7 @@ impl Tree {
} }
struct TreeBuilder<'a> { struct TreeBuilder<'a> {
ctx: &'a Context<'a>,
opt: &'a Options, opt: &'a Options,
txn: &'a Transaction, txn: &'a Transaction,
table: &'a Table, table: &'a Table,
@ -74,6 +78,10 @@ impl<'a> TreeBuilder<'a> {
Value::Number(_) => Node::Scalar(v.to_owned()), Value::Number(_) => Node::Scalar(v.to_owned()),
Value::Bool(_) => Node::Scalar(v.to_owned()), Value::Bool(_) => Node::Scalar(v.to_owned()),
Value::Subquery(s) => self.eval_subquery(s).await?, 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, _ => Node::Unsupported,
}) })
} }

View file

@ -89,7 +89,7 @@ impl SelectStatement {
let v = w.compute(ctx, opt).await?; let v = w.compute(ctx, opt).await?;
match v { match v {
Value::Table(t) => { 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::Thing(v) => i.ingest(Iterable::Thing(v)),
Value::Range(v) => i.ingest(Iterable::Range(*v)), Value::Range(v) => i.ingest(Iterable::Range(*v)),

View file

@ -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'; CREATE blog:4 SET title = 'the dog sat there and did nothing';
DEFINE ANALYZER simple TOKENIZERS blank,class; DEFINE ANALYZER simple TOKENIZERS blank,class;
DEFINE INDEX blog_title ON blog FIELDS title SEARCH ANALYZER simple BM25 HIGHLIGHTS; 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'; 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 dbs = Datastore::new("memory").await?;
let ses = Session::for_kv().with_ns("test").with_db("test"); let ses = Session::for_kv().with_ns("test").with_db("test");
let res = &mut dbs.execute(&sql, &ses, None, false).await?; 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?; let _ = res.remove(0).result?;
} }