Only allow for single values in RELATE statements
This commit is contained in:
parent
37a3efc81b
commit
18cee9091a
1 changed files with 89 additions and 78 deletions
|
@ -6,18 +6,23 @@ use crate::dbs::Options;
|
||||||
use crate::dbs::Statement;
|
use crate::dbs::Statement;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
|
use crate::sql::array::array;
|
||||||
use crate::sql::comment::mightbespace;
|
use crate::sql::comment::mightbespace;
|
||||||
use crate::sql::comment::shouldbespace;
|
use crate::sql::comment::shouldbespace;
|
||||||
use crate::sql::data::{data, Data};
|
use crate::sql::data::{data, Data};
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::output::{output, Output};
|
use crate::sql::output::{output, Output};
|
||||||
|
use crate::sql::param::param;
|
||||||
|
use crate::sql::subquery::subquery;
|
||||||
use crate::sql::table::{table, Table};
|
use crate::sql::table::{table, Table};
|
||||||
|
use crate::sql::thing::thing;
|
||||||
use crate::sql::timeout::{timeout, Timeout};
|
use crate::sql::timeout::{timeout, Timeout};
|
||||||
use crate::sql::value::{whats, Value, Values};
|
use crate::sql::value::Value;
|
||||||
use derive::Store;
|
use derive::Store;
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::tag_no_case;
|
use nom::bytes::complete::tag_no_case;
|
||||||
use nom::character::complete::char;
|
use nom::character::complete::char;
|
||||||
|
use nom::combinator::map;
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
use nom::sequence::preceded;
|
use nom::sequence::preceded;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -26,8 +31,8 @@ use std::fmt;
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Store)]
|
||||||
pub struct RelateStatement {
|
pub struct RelateStatement {
|
||||||
pub kind: Table,
|
pub kind: Table,
|
||||||
pub from: Values,
|
pub from: Value,
|
||||||
pub with: Values,
|
pub with: Value,
|
||||||
pub uniq: bool,
|
pub uniq: bool,
|
||||||
pub data: Option<Data>,
|
pub data: Option<Data>,
|
||||||
pub output: Option<Output>,
|
pub output: Option<Output>,
|
||||||
|
@ -56,89 +61,84 @@ impl RelateStatement {
|
||||||
// Loop over the from targets
|
// Loop over the from targets
|
||||||
let from = {
|
let from = {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
for w in self.from.0.iter() {
|
match self.from.compute(ctx, opt, txn, doc).await? {
|
||||||
let v = w.compute(ctx, opt, txn, doc).await?;
|
Value::Thing(v) => out.push(v),
|
||||||
match v {
|
Value::Array(v) => {
|
||||||
Value::Thing(v) => out.push(v),
|
for v in v {
|
||||||
Value::Array(v) => {
|
match v {
|
||||||
for v in v {
|
Value::Thing(v) => out.push(v),
|
||||||
match v {
|
Value::Object(v) => match v.rid() {
|
||||||
Value::Thing(v) => out.push(v),
|
Some(v) => out.push(v),
|
||||||
Value::Object(v) => match v.rid() {
|
_ => {
|
||||||
Some(v) => out.push(v),
|
|
||||||
_ => {
|
|
||||||
return Err(Error::RelateStatement {
|
|
||||||
value: v.to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
v => {
|
|
||||||
return Err(Error::RelateStatement {
|
return Err(Error::RelateStatement {
|
||||||
value: v.to_string(),
|
value: v.to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
v => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Object(v) => match v.rid() {
|
}
|
||||||
Some(v) => out.push(v),
|
Value::Object(v) => match v.rid() {
|
||||||
None => {
|
Some(v) => out.push(v),
|
||||||
return Err(Error::RelateStatement {
|
None => {
|
||||||
value: v.to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
v => {
|
|
||||||
return Err(Error::RelateStatement {
|
return Err(Error::RelateStatement {
|
||||||
value: v.to_string(),
|
value: v.to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
}
|
v => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// }
|
||||||
out
|
out
|
||||||
};
|
};
|
||||||
// Loop over the with targets
|
// Loop over the with targets
|
||||||
let with = {
|
let with = {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
for w in self.with.0.iter() {
|
match self.with.compute(ctx, opt, txn, doc).await? {
|
||||||
let v = w.compute(ctx, opt, txn, doc).await?;
|
Value::Thing(v) => out.push(v),
|
||||||
match v {
|
Value::Array(v) => {
|
||||||
Value::Thing(v) => out.push(v),
|
for v in v {
|
||||||
Value::Array(v) => {
|
match v {
|
||||||
for v in v {
|
Value::Thing(v) => out.push(v),
|
||||||
match v {
|
Value::Object(v) => match v.rid() {
|
||||||
Value::Thing(v) => out.push(v),
|
Some(v) => out.push(v),
|
||||||
Value::Object(v) => match v.rid() {
|
None => {
|
||||||
Some(v) => out.push(v),
|
|
||||||
None => {
|
|
||||||
return Err(Error::RelateStatement {
|
|
||||||
value: v.to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
v => {
|
|
||||||
return Err(Error::RelateStatement {
|
return Err(Error::RelateStatement {
|
||||||
value: v.to_string(),
|
value: v.to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
v => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Value::Object(v) => match v.rid() {
|
}
|
||||||
Some(v) => out.push(v),
|
Value::Object(v) => match v.rid() {
|
||||||
None => {
|
Some(v) => out.push(v),
|
||||||
return Err(Error::RelateStatement {
|
None => {
|
||||||
value: v.to_string(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
v => {
|
|
||||||
return Err(Error::RelateStatement {
|
return Err(Error::RelateStatement {
|
||||||
value: v.to_string(),
|
value: v.to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
}
|
v => {
|
||||||
|
return Err(Error::RelateStatement {
|
||||||
|
value: v.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
out
|
out
|
||||||
};
|
};
|
||||||
//
|
//
|
||||||
|
@ -203,8 +203,13 @@ pub fn relate(i: &str) -> IResult<&str, RelateStatement> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn relate_o(i: &str) -> IResult<&str, (Table, Values, Values)> {
|
fn relate_o(i: &str) -> IResult<&str, (Table, Value, Value)> {
|
||||||
let (i, from) = whats(i)?;
|
let (i, from) = alt((
|
||||||
|
map(subquery, Value::from),
|
||||||
|
map(array, Value::from),
|
||||||
|
map(param, Value::from),
|
||||||
|
map(thing, Value::from),
|
||||||
|
))(i)?;
|
||||||
let (i, _) = mightbespace(i)?;
|
let (i, _) = mightbespace(i)?;
|
||||||
let (i, _) = char('-')(i)?;
|
let (i, _) = char('-')(i)?;
|
||||||
let (i, _) = char('>')(i)?;
|
let (i, _) = char('>')(i)?;
|
||||||
|
@ -214,12 +219,22 @@ fn relate_o(i: &str) -> IResult<&str, (Table, Values, Values)> {
|
||||||
let (i, _) = char('-')(i)?;
|
let (i, _) = char('-')(i)?;
|
||||||
let (i, _) = char('>')(i)?;
|
let (i, _) = char('>')(i)?;
|
||||||
let (i, _) = mightbespace(i)?;
|
let (i, _) = mightbespace(i)?;
|
||||||
let (i, with) = whats(i)?;
|
let (i, with) = alt((
|
||||||
|
map(subquery, Value::from),
|
||||||
|
map(array, Value::from),
|
||||||
|
map(param, Value::from),
|
||||||
|
map(thing, Value::from),
|
||||||
|
))(i)?;
|
||||||
Ok((i, (kind, from, with)))
|
Ok((i, (kind, from, with)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn relate_i(i: &str) -> IResult<&str, (Table, Values, Values)> {
|
fn relate_i(i: &str) -> IResult<&str, (Table, Value, Value)> {
|
||||||
let (i, with) = whats(i)?;
|
let (i, with) = alt((
|
||||||
|
map(subquery, Value::from),
|
||||||
|
map(array, Value::from),
|
||||||
|
map(param, Value::from),
|
||||||
|
map(thing, Value::from),
|
||||||
|
))(i)?;
|
||||||
let (i, _) = mightbespace(i)?;
|
let (i, _) = mightbespace(i)?;
|
||||||
let (i, _) = char('<')(i)?;
|
let (i, _) = char('<')(i)?;
|
||||||
let (i, _) = char('-')(i)?;
|
let (i, _) = char('-')(i)?;
|
||||||
|
@ -229,7 +244,12 @@ fn relate_i(i: &str) -> IResult<&str, (Table, Values, Values)> {
|
||||||
let (i, _) = char('<')(i)?;
|
let (i, _) = char('<')(i)?;
|
||||||
let (i, _) = char('-')(i)?;
|
let (i, _) = char('-')(i)?;
|
||||||
let (i, _) = mightbespace(i)?;
|
let (i, _) = mightbespace(i)?;
|
||||||
let (i, from) = whats(i)?;
|
let (i, from) = alt((
|
||||||
|
map(subquery, Value::from),
|
||||||
|
map(array, Value::from),
|
||||||
|
map(param, Value::from),
|
||||||
|
map(thing, Value::from),
|
||||||
|
))(i)?;
|
||||||
Ok((i, (kind, from, with)))
|
Ok((i, (kind, from, with)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,28 +260,19 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn relate_statement_in() {
|
fn relate_statement_in() {
|
||||||
let sql = "RELATE person->like->animal";
|
let sql = "RELATE person:tobie->like->animal:koala";
|
||||||
let res = relate(sql);
|
let res = relate(sql);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let out = res.unwrap().1;
|
let out = res.unwrap().1;
|
||||||
assert_eq!("RELATE person -> like -> animal", format!("{}", out))
|
assert_eq!("RELATE person:tobie -> like -> animal:koala", format!("{}", out))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn relate_statement_out() {
|
fn relate_statement_out() {
|
||||||
let sql = "RELATE animal<-like<-person";
|
let sql = "RELATE animal:koala<-like<-person:tobie";
|
||||||
let res = relate(sql);
|
let res = relate(sql);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let out = res.unwrap().1;
|
let out = res.unwrap().1;
|
||||||
assert_eq!("RELATE person -> like -> animal", format!("{}", out))
|
assert_eq!("RELATE person:tobie -> like -> animal:koala", format!("{}", out))
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn relate_statement_thing() {
|
|
||||||
let sql = "RELATE person:tobie->like->person:jaime";
|
|
||||||
let res = relate(sql);
|
|
||||||
assert!(res.is_ok());
|
|
||||||
let out = res.unwrap().1;
|
|
||||||
assert_eq!("RELATE person:tobie -> like -> person:jaime", format!("{}", out))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue