Skip to content

Commit

Permalink
Fix index plan for idiom param value (surrealdb#2865)
Browse files Browse the repository at this point in the history
  • Loading branch information
hchockarprasad authored Oct 25, 2023
1 parent bc2f7fd commit cfdd7c1
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 1 deletion.
9 changes: 8 additions & 1 deletion lib/src/idx/planner/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::err::Error;
use crate::idx::planner::plan::{IndexOperator, IndexOption};
use crate::sql::index::Index;
use crate::sql::statements::DefineIndexStatement;
use crate::sql::{Array, Cond, Expression, Idiom, Operator, Subquery, Table, Value, With};
use crate::sql::{Array, Cond, Expression, Idiom, Operator, Part, Subquery, Table, Value, With};
use async_recursion::async_recursion;
use std::collections::HashMap;
use std::sync::Arc;
Expand Down Expand Up @@ -126,6 +126,13 @@ impl<'a> TreeBuilder<'a> {
}

async fn eval_idiom(&mut self, i: &Idiom) -> Result<Node, Error> {
// Compute the idiom value if it is a param
if let Some(Part::Start(x)) = i.0.first() {
if x.is_param() {
let v = i.compute(self.ctx, self.opt, self.txn, None).await?;
return self.eval_value(&v).await;
}
}
if let Some(irs) = self.find_indexes(i).await? {
if !irs.is_empty() {
return Ok(Node::IndexedField(i.to_owned(), irs));
Expand Down
5 changes: 5 additions & 0 deletions lib/src/sql/value/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,11 @@ impl Value {
}
}

/// Check if this Value is a Param
pub fn is_param(&self) -> bool {
matches!(self, Value::Param(_))
}

/// Check if this Value is a Geometry of a specific type
pub fn is_geometry_type(&self, types: &[String]) -> bool {
match self {
Expand Down
40 changes: 40 additions & 0 deletions lib/tests/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -846,3 +846,43 @@ async fn select_index_single_range_operator_more_or_equal() -> Result<(), Error>
async fn select_unique_single_range_operator_more_or_equal() -> Result<(), Error> {
select_single_range_operator(true, ">=", EXPLAIN_MORE_OR_EQUAL, RESULT_MORE_OR_EQUAL).await
}

#[tokio::test]
async fn select_with_idiom_param_value() -> Result<(), Error> {
let dbs = new_ds().await?;
let ses = Session::owner().with_ns("test").with_db("test");
let sql = format!(
"
CREATE person:tobie SET name = 'Tobie', genre='m', company='SurrealDB';
CREATE person:jaime SET name = 'Jaime', genre='m', company='SurrealDB';
DEFINE INDEX name ON TABLE person COLUMNS name UNIQUE;
LET $name = 'Tobie';
LET $nameObj = {{name:'Tobie'}};
SELECT name FROM person WHERE name = $nameObj.name EXPLAIN;"
);
let mut res = dbs.execute(&sql, &ses, None).await?;
assert_eq!(res.len(), 6);
res.remove(0).result?;
res.remove(0).result?;
res.remove(0).result?;
res.remove(0).result?;
res.remove(0).result?;
let tmp = res.remove(0).result?;
let val = Value::parse(
r#"[
{
detail: {
plan: {
index: 'name',
operator: '=',
value: 'Tobie'
},
table: 'person'
},
operation: 'Iterate Index'
}
]"#,
);
assert_eq!(format!("{:#}", tmp), format!("{:#}", val));
Ok(())
}

0 comments on commit cfdd7c1

Please sign in to comment.