Add initial support for additional functionality in graph expressions
Related to #1658
This commit is contained in:
parent
2e0093c41d
commit
0a328d4f0a
4 changed files with 92 additions and 4 deletions
|
@ -21,12 +21,18 @@ use std::ops::Deref;
|
|||
pub struct Fields(pub Vec<Field>, pub bool);
|
||||
|
||||
impl Fields {
|
||||
pub fn all(&self) -> bool {
|
||||
pub fn all() -> Self {
|
||||
Self(vec![Field::All], false)
|
||||
}
|
||||
/// Check to see if this field is a * projection
|
||||
pub fn is_all(&self) -> bool {
|
||||
self.0.iter().any(|v| matches!(v, Field::All))
|
||||
}
|
||||
/// Get all fields which are not an * projection
|
||||
pub fn other(&self) -> impl Iterator<Item = &Field> {
|
||||
self.0.iter().filter(|v| !matches!(v, Field::All))
|
||||
}
|
||||
/// Check to see if this field is a single VALUE clause
|
||||
pub fn single(&self) -> Option<&Field> {
|
||||
match (self.0.len(), self.1) {
|
||||
(1, true) => match self.0.first() {
|
||||
|
@ -77,7 +83,7 @@ impl Fields {
|
|||
//
|
||||
let doc = doc.unwrap_or(&Value::None);
|
||||
// Process the desired output
|
||||
let mut out = match self.all() {
|
||||
let mut out = match self.is_all() {
|
||||
true => doc.compute(ctx, opt, txn, Some(doc)).await?,
|
||||
false => Value::base(),
|
||||
};
|
||||
|
|
|
@ -3,7 +3,13 @@ use crate::sql::comment::shouldbespace;
|
|||
use crate::sql::cond::{cond, Cond};
|
||||
use crate::sql::dir::{dir, Dir};
|
||||
use crate::sql::error::IResult;
|
||||
use crate::sql::field::Fields;
|
||||
use crate::sql::group::Groups;
|
||||
use crate::sql::idiom::{plain as idiom, Idiom};
|
||||
use crate::sql::limit::Limit;
|
||||
use crate::sql::order::Orders;
|
||||
use crate::sql::split::Splits;
|
||||
use crate::sql::start::Start;
|
||||
use crate::sql::table::{table, tables, Tables};
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::tag_no_case;
|
||||
|
@ -16,8 +22,14 @@ use std::fmt::{self, Display, Formatter, Write};
|
|||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
|
||||
pub struct Graph {
|
||||
pub dir: Dir,
|
||||
pub expr: Fields,
|
||||
pub what: Tables,
|
||||
pub cond: Option<Cond>,
|
||||
pub split: Option<Splits>,
|
||||
pub group: Option<Groups>,
|
||||
pub order: Option<Orders>,
|
||||
pub limit: Option<Limit>,
|
||||
pub start: Option<Start>,
|
||||
pub alias: Option<Idiom>,
|
||||
}
|
||||
|
||||
|
@ -45,6 +57,21 @@ impl Display for Graph {
|
|||
if let Some(ref v) = self.cond {
|
||||
write!(f, " {v}")?
|
||||
}
|
||||
if let Some(ref v) = self.split {
|
||||
write!(f, " {v}")?
|
||||
}
|
||||
if let Some(ref v) = self.group {
|
||||
write!(f, " {v}")?
|
||||
}
|
||||
if let Some(ref v) = self.order {
|
||||
write!(f, " {v}")?
|
||||
}
|
||||
if let Some(ref v) = self.limit {
|
||||
write!(f, " {v}")?
|
||||
}
|
||||
if let Some(ref v) = self.start {
|
||||
write!(f, " {v}")?
|
||||
}
|
||||
if let Some(ref v) = self.alias {
|
||||
write!(f, " AS {v}")?
|
||||
}
|
||||
|
@ -60,9 +87,15 @@ pub fn graph(i: &str) -> IResult<&str, Graph> {
|
|||
i,
|
||||
Graph {
|
||||
dir,
|
||||
expr: Fields::all(),
|
||||
what,
|
||||
cond,
|
||||
alias,
|
||||
split: None,
|
||||
group: None,
|
||||
order: None,
|
||||
limit: None,
|
||||
start: None,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
|
|
@ -245,6 +245,7 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::sql::dir::Dir;
|
||||
use crate::sql::expression::Expression;
|
||||
use crate::sql::field::Fields;
|
||||
use crate::sql::graph::Graph;
|
||||
use crate::sql::number::Number;
|
||||
use crate::sql::param::Param;
|
||||
|
@ -410,15 +411,27 @@ mod tests {
|
|||
Part::from("friend"),
|
||||
Part::Graph(Graph {
|
||||
dir: Dir::Out,
|
||||
expr: Fields::all(),
|
||||
what: Table::from("like").into(),
|
||||
cond: None,
|
||||
alias: None,
|
||||
split: None,
|
||||
group: None,
|
||||
order: None,
|
||||
limit: None,
|
||||
start: None,
|
||||
}),
|
||||
Part::Graph(Graph {
|
||||
dir: Dir::Out,
|
||||
expr: Fields::all(),
|
||||
what: Table::from("person").into(),
|
||||
cond: None,
|
||||
alias: None,
|
||||
split: None,
|
||||
group: None,
|
||||
order: None,
|
||||
limit: None,
|
||||
start: None,
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
use crate::err::Error;
|
||||
use crate::sql::field::Fields;
|
||||
use crate::sql::group::Groups;
|
||||
use crate::sql::limit::Limit;
|
||||
use crate::sql::order::Orders;
|
||||
use crate::sql::split::Splits;
|
||||
use crate::sql::start::Start;
|
||||
use crate::sql::value::serde::ser;
|
||||
use crate::sql::Cond;
|
||||
use crate::sql::Dir;
|
||||
|
@ -39,8 +45,14 @@ impl ser::Serializer for Serializer {
|
|||
#[derive(Default)]
|
||||
pub(super) struct SerializeGraph {
|
||||
dir: Option<Dir>,
|
||||
expr: Option<Fields>,
|
||||
what: Option<Tables>,
|
||||
cond: Option<Cond>,
|
||||
split: Option<Splits>,
|
||||
group: Option<Groups>,
|
||||
order: Option<Orders>,
|
||||
limit: Option<Limit>,
|
||||
start: Option<Start>,
|
||||
alias: Option<Idiom>,
|
||||
}
|
||||
|
||||
|
@ -56,12 +68,30 @@ impl serde::ser::SerializeStruct for SerializeGraph {
|
|||
"dir" => {
|
||||
self.dir = Some(value.serialize(ser::dir::Serializer.wrap())?);
|
||||
}
|
||||
"expr" => {
|
||||
self.expr = Some(value.serialize(ser::fields::Serializer.wrap())?);
|
||||
}
|
||||
"what" => {
|
||||
self.what = Some(Tables(value.serialize(ser::table::vec::Serializer.wrap())?));
|
||||
}
|
||||
"cond" => {
|
||||
self.cond = value.serialize(ser::cond::opt::Serializer.wrap())?;
|
||||
}
|
||||
"split" => {
|
||||
self.split = value.serialize(ser::split::vec::opt::Serializer.wrap())?.map(Splits);
|
||||
}
|
||||
"group" => {
|
||||
self.group = value.serialize(ser::group::vec::opt::Serializer.wrap())?.map(Groups);
|
||||
}
|
||||
"order" => {
|
||||
self.order = value.serialize(ser::order::vec::opt::Serializer.wrap())?.map(Orders);
|
||||
}
|
||||
"limit" => {
|
||||
self.limit = value.serialize(ser::limit::opt::Serializer.wrap())?;
|
||||
}
|
||||
"start" => {
|
||||
self.start = value.serialize(ser::start::opt::Serializer.wrap())?;
|
||||
}
|
||||
"alias" => {
|
||||
self.alias = value.serialize(ser::part::vec::opt::Serializer.wrap())?.map(Idiom);
|
||||
}
|
||||
|
@ -73,11 +103,17 @@ impl serde::ser::SerializeStruct for SerializeGraph {
|
|||
}
|
||||
|
||||
fn end(self) -> Result<Self::Ok, Error> {
|
||||
match (self.dir, self.what) {
|
||||
(Some(dir), Some(what)) => Ok(Graph {
|
||||
match (self.dir, self.expr, self.what) {
|
||||
(Some(dir), Some(expr), Some(what)) => Ok(Graph {
|
||||
dir,
|
||||
expr,
|
||||
what,
|
||||
cond: self.cond,
|
||||
split: self.split,
|
||||
group: self.group,
|
||||
order: self.order,
|
||||
limit: self.limit,
|
||||
start: self.start,
|
||||
alias: self.alias,
|
||||
}),
|
||||
_ => Err(Error::custom("`Graph` missing required field(s)")),
|
||||
|
|
Loading…
Reference in a new issue