Fix index plan for idiom param value (#2865)

This commit is contained in:
hchockarprasad 2023-10-25 15:54:04 +05:30 committed by GitHub
parent bc2f7fdafa
commit cfdd7c195c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 1 deletions

View file

@ -4,7 +4,7 @@ use crate::err::Error;
use crate::idx::planner::plan::{IndexOperator, IndexOption}; use crate::idx::planner::plan::{IndexOperator, IndexOption};
use crate::sql::index::Index; use crate::sql::index::Index;
use crate::sql::statements::DefineIndexStatement; 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 async_recursion::async_recursion;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
@ -126,6 +126,13 @@ impl<'a> TreeBuilder<'a> {
} }
async fn eval_idiom(&mut self, i: &Idiom) -> Result<Node, Error> { 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 let Some(irs) = self.find_indexes(i).await? {
if !irs.is_empty() { if !irs.is_empty() {
return Ok(Node::IndexedField(i.to_owned(), irs)); return Ok(Node::IndexedField(i.to_owned(), irs));

View file

@ -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 /// Check if this Value is a Geometry of a specific type
pub fn is_geometry_type(&self, types: &[String]) -> bool { pub fn is_geometry_type(&self, types: &[String]) -> bool {
match self { match self {

View file

@ -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> { 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 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(())
}