Check that objects properties are recognized by the query planner (#3643)

This commit is contained in:
Emmanuel Keller 2024-03-07 16:45:05 +00:00 committed by GitHub
parent 03e9998ff1
commit 1784a1202e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 52 additions and 42 deletions

View file

@ -10,10 +10,9 @@ use crate::sql::Ident;
use crate::sql::{filter::Filter, statements::DefineAnalyzerStatement, Strand, Tokenizer}; use crate::sql::{filter::Filter, statements::DefineAnalyzerStatement, Strand, Tokenizer};
#[cfg(feature = "sql2")] #[cfg(feature = "sql2")]
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::{ use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0, #[cfg(feature = "sql2")]
sequence::tuple, use nom::{combinator::opt, sequence::tuple};
};
pub fn analyzer(i: &str) -> IResult<&str, DefineAnalyzerStatement> { pub fn analyzer(i: &str) -> IResult<&str, DefineAnalyzerStatement> {
let (i, _) = tag_no_case("ANALYZER")(i)?; let (i, _) = tag_no_case("ANALYZER")(i)?;

View file

@ -7,10 +7,9 @@ use super::super::super::{
IResult, IResult,
}; };
use crate::sql::{statements::DefineDatabaseStatement, ChangeFeed, Strand}; use crate::sql::{statements::DefineDatabaseStatement, ChangeFeed, Strand};
use nom::{ use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0, #[cfg(feature = "sql2")]
sequence::tuple, use nom::{combinator::opt, sequence::tuple};
};
pub fn database(i: &str) -> IResult<&str, DefineDatabaseStatement> { pub fn database(i: &str) -> IResult<&str, DefineDatabaseStatement> {
let (i, _) = alt((tag_no_case("DB"), tag_no_case("DATABASE")))(i)?; let (i, _) = alt((tag_no_case("DB"), tag_no_case("DATABASE")))(i)?;

View file

@ -15,10 +15,10 @@ use nom::{
bytes::complete::{tag, tag_no_case}, bytes::complete::{tag, tag_no_case},
character::complete::char, character::complete::char,
combinator::cut, combinator::cut,
combinator::opt,
multi::many0, multi::many0,
sequence::tuple,
}; };
#[cfg(feature = "sql2")]
use nom::{combinator::opt, sequence::tuple};
pub fn function(i: &str) -> IResult<&str, DefineFunctionStatement> { pub fn function(i: &str) -> IResult<&str, DefineFunctionStatement> {
let (i, _) = tag_no_case("FUNCTION")(i)?; let (i, _) = tag_no_case("FUNCTION")(i)?;

View file

@ -6,10 +6,9 @@ use super::super::super::{
IResult, IResult,
}; };
use crate::sql::{statements::DefineNamespaceStatement, Strand}; use crate::sql::{statements::DefineNamespaceStatement, Strand};
use nom::{ use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0, #[cfg(feature = "sql2")]
sequence::tuple, use nom::{combinator::opt, sequence::tuple};
};
pub fn namespace(i: &str) -> IResult<&str, DefineNamespaceStatement> { pub fn namespace(i: &str) -> IResult<&str, DefineNamespaceStatement> {
let (i, _) = alt((tag_no_case("NS"), tag_no_case("NAMESPACE")))(i)?; let (i, _) = alt((tag_no_case("NS"), tag_no_case("NAMESPACE")))(i)?;

View file

@ -13,8 +13,10 @@ use crate::{
}; };
use nom::{ use nom::{
branch::alt, bytes::complete::tag_no_case, character::complete::char, combinator::cut, branch::alt, bytes::complete::tag_no_case, character::complete::char, combinator::cut,
combinator::opt, multi::many0, sequence::tuple, Err, multi::many0, Err,
}; };
#[cfg(feature = "sql2")]
use nom::{combinator::opt, sequence::tuple};
pub fn param(i: &str) -> IResult<&str, DefineParamStatement> { pub fn param(i: &str) -> IResult<&str, DefineParamStatement> {
let (i, _) = tag_no_case("PARAM")(i)?; let (i, _) = tag_no_case("PARAM")(i)?;

View file

@ -7,10 +7,9 @@ use super::super::super::{
IResult, IResult,
}; };
use crate::sql::{statements::DefineScopeStatement, Duration, Strand, Value}; use crate::sql::{statements::DefineScopeStatement, Duration, Strand, Value};
use nom::{ use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0, #[cfg(feature = "sql2")]
sequence::tuple, use nom::{combinator::opt, sequence::tuple};
};
pub fn scope(i: &str) -> IResult<&str, DefineScopeStatement> { pub fn scope(i: &str) -> IResult<&str, DefineScopeStatement> {
let (i, _) = tag_no_case("SCOPE")(i)?; let (i, _) = tag_no_case("SCOPE")(i)?;

View file

@ -9,10 +9,9 @@ use super::super::super::{
use crate::sql::{ use crate::sql::{
statements::DefineTableStatement, ChangeFeed, Permission, Permissions, Strand, View, statements::DefineTableStatement, ChangeFeed, Permission, Permissions, Strand, View,
}; };
use nom::{ use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0, #[cfg(feature = "sql2")]
sequence::tuple, use nom::{combinator::opt, sequence::tuple};
};
pub fn table(i: &str) -> IResult<&str, DefineTableStatement> { pub fn table(i: &str) -> IResult<&str, DefineTableStatement> {
let (i, _) = tag_no_case("TABLE")(i)?; let (i, _) = tag_no_case("TABLE")(i)?;

View file

@ -13,10 +13,9 @@ use crate::{
syn::v1::ParseError, syn::v1::ParseError,
}; };
use nom::Err; use nom::Err;
use nom::{ use nom::{branch::alt, bytes::complete::tag_no_case, combinator::cut, multi::many0};
branch::alt, bytes::complete::tag_no_case, combinator::cut, combinator::opt, multi::many0, #[cfg(feature = "sql2")]
sequence::tuple, use nom::{combinator::opt, sequence::tuple};
};
pub fn token(i: &str) -> IResult<&str, DefineTokenStatement> { pub fn token(i: &str) -> IResult<&str, DefineTokenStatement> {
let (i, _) = tag_no_case("TOKEN")(i)?; let (i, _) = tag_no_case("TOKEN")(i)?;

View file

@ -15,11 +15,11 @@ use nom::{
branch::alt, branch::alt,
bytes::complete::tag_no_case, bytes::complete::tag_no_case,
combinator::cut, combinator::cut,
combinator::opt,
multi::{many0, separated_list1}, multi::{many0, separated_list1},
sequence::tuple,
Err, Err,
}; };
#[cfg(feature = "sql2")]
use nom::{combinator::opt, sequence::tuple};
pub fn user(i: &str) -> IResult<&str, DefineUserStatement> { pub fn user(i: &str) -> IResult<&str, DefineUserStatement> {
let (i, _) = tag_no_case("USER")(i)?; let (i, _) = tag_no_case("USER")(i)?;

View file

@ -1147,6 +1147,9 @@ async fn select_unique_contains() -> Result<(), Error> {
} }
#[tokio::test] #[tokio::test]
// This test checks that:
// 1. Datetime are recognized by the query planner
// 2. we can take the value store in a variable
async fn select_with_datetime_value() -> Result<(), Error> { async fn select_with_datetime_value() -> Result<(), Error> {
let dbs = new_ds().await?; let dbs = new_ds().await?;
let ses = Session::owner().with_ns("test").with_db("test"); let ses = Session::owner().with_ns("test").with_db("test");
@ -1201,6 +1204,9 @@ async fn select_with_datetime_value() -> Result<(), Error> {
} }
#[tokio::test] #[tokio::test]
// This test checks that:
// 1. UUID are recognized by the query planner
// 2. we can take the value from a object stored as a variable
async fn select_with_uuid_value() -> Result<(), Error> { async fn select_with_uuid_value() -> Result<(), Error> {
let dbs = new_ds().await?; let dbs = new_ds().await?;
let ses = Session::owner().with_ns("test").with_db("test"); let ses = Session::owner().with_ns("test").with_db("test");
@ -1208,16 +1214,21 @@ async fn select_with_uuid_value() -> Result<(), Error> {
let sql = " let sql = "
DEFINE INDEX sessionUid ON sessions FIELDS sessionUid; DEFINE INDEX sessionUid ON sessions FIELDS sessionUid;
CREATE sessions:1 CONTENT { sessionUid: u'00ad70db-f435-442e-9012-1cd853102084' }; CREATE sessions:1 CONTENT { sessionUid: u'00ad70db-f435-442e-9012-1cd853102084' };
LET $sess = { uuid: u'00ad70db-f435-442e-9012-1cd853102084' };
SELECT * FROM sessions WHERE sessionUid = u'00ad70db-f435-442e-9012-1cd853102084' EXPLAIN; SELECT * FROM sessions WHERE sessionUid = u'00ad70db-f435-442e-9012-1cd853102084' EXPLAIN;
SELECT * FROM sessions WHERE sessionUid = u'00ad70db-f435-442e-9012-1cd853102084';"; SELECT * FROM sessions WHERE sessionUid = $sess.uuid EXPLAIN;
SELECT * FROM sessions WHERE sessionUid = u'00ad70db-f435-442e-9012-1cd853102084';
SELECT * FROM sessions WHERE sessionUid = $sess.uuid;
";
let mut res = dbs.execute(&sql, &ses, None).await?; let mut res = dbs.execute(&sql, &ses, None).await?;
assert_eq!(res.len(), 4); assert_eq!(res.len(), 7);
skip_ok(&mut res, 2)?; skip_ok(&mut res, 3)?;
let tmp = res.remove(0).result?; for _ in 0..2 {
let val = Value::parse( let tmp = res.remove(0).result?;
r#"[ let val = Value::parse(
r#"[
{ {
detail: { detail: {
plan: { plan: {
@ -1230,19 +1241,22 @@ async fn select_with_uuid_value() -> Result<(), Error> {
operation: 'Iterate Index' operation: 'Iterate Index'
} }
]"#, ]"#,
); );
assert_eq!(format!("{:#}", tmp), format!("{:#}", val)); assert_eq!(format!("{:#}", tmp), format!("{:#}", val));
}
let tmp = res.remove(0).result?; for _ in 0..2 {
let val = Value::parse( let tmp = res.remove(0).result?;
r#"[ let val = Value::parse(
r#"[
{ {
"id": sessions:1, "id": sessions:1,
"sessionUid": "00ad70db-f435-442e-9012-1cd853102084" "sessionUid": "00ad70db-f435-442e-9012-1cd853102084"
} }
]"#, ]"#,
); );
assert_eq!(format!("{:#}", tmp), format!("{:#}", val)); assert_eq!(format!("{:#}", tmp), format!("{:#}", val));
}
Ok(()) Ok(())
} }