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);
|
pub struct Fields(pub Vec<Field>, pub bool);
|
||||||
|
|
||||||
impl Fields {
|
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))
|
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> {
|
pub fn other(&self) -> impl Iterator<Item = &Field> {
|
||||||
self.0.iter().filter(|v| !matches!(v, Field::All))
|
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> {
|
pub fn single(&self) -> Option<&Field> {
|
||||||
match (self.0.len(), self.1) {
|
match (self.0.len(), self.1) {
|
||||||
(1, true) => match self.0.first() {
|
(1, true) => match self.0.first() {
|
||||||
|
@ -77,7 +83,7 @@ impl Fields {
|
||||||
//
|
//
|
||||||
let doc = doc.unwrap_or(&Value::None);
|
let doc = doc.unwrap_or(&Value::None);
|
||||||
// Process the desired output
|
// 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?,
|
true => doc.compute(ctx, opt, txn, Some(doc)).await?,
|
||||||
false => Value::base(),
|
false => Value::base(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,13 @@ use crate::sql::comment::shouldbespace;
|
||||||
use crate::sql::cond::{cond, Cond};
|
use crate::sql::cond::{cond, Cond};
|
||||||
use crate::sql::dir::{dir, Dir};
|
use crate::sql::dir::{dir, Dir};
|
||||||
use crate::sql::error::IResult;
|
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::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 crate::sql::table::{table, tables, Tables};
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::tag_no_case;
|
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)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
|
||||||
pub struct Graph {
|
pub struct Graph {
|
||||||
pub dir: Dir,
|
pub dir: Dir,
|
||||||
|
pub expr: Fields,
|
||||||
pub what: Tables,
|
pub what: Tables,
|
||||||
pub cond: Option<Cond>,
|
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>,
|
pub alias: Option<Idiom>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +57,21 @@ impl Display for Graph {
|
||||||
if let Some(ref v) = self.cond {
|
if let Some(ref v) = self.cond {
|
||||||
write!(f, " {v}")?
|
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 {
|
if let Some(ref v) = self.alias {
|
||||||
write!(f, " AS {v}")?
|
write!(f, " AS {v}")?
|
||||||
}
|
}
|
||||||
|
@ -60,9 +87,15 @@ pub fn graph(i: &str) -> IResult<&str, Graph> {
|
||||||
i,
|
i,
|
||||||
Graph {
|
Graph {
|
||||||
dir,
|
dir,
|
||||||
|
expr: Fields::all(),
|
||||||
what,
|
what,
|
||||||
cond,
|
cond,
|
||||||
alias,
|
alias,
|
||||||
|
split: None,
|
||||||
|
group: None,
|
||||||
|
order: None,
|
||||||
|
limit: None,
|
||||||
|
start: None,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -245,6 +245,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::sql::dir::Dir;
|
use crate::sql::dir::Dir;
|
||||||
use crate::sql::expression::Expression;
|
use crate::sql::expression::Expression;
|
||||||
|
use crate::sql::field::Fields;
|
||||||
use crate::sql::graph::Graph;
|
use crate::sql::graph::Graph;
|
||||||
use crate::sql::number::Number;
|
use crate::sql::number::Number;
|
||||||
use crate::sql::param::Param;
|
use crate::sql::param::Param;
|
||||||
|
@ -410,15 +411,27 @@ mod tests {
|
||||||
Part::from("friend"),
|
Part::from("friend"),
|
||||||
Part::Graph(Graph {
|
Part::Graph(Graph {
|
||||||
dir: Dir::Out,
|
dir: Dir::Out,
|
||||||
|
expr: Fields::all(),
|
||||||
what: Table::from("like").into(),
|
what: Table::from("like").into(),
|
||||||
cond: None,
|
cond: None,
|
||||||
alias: None,
|
alias: None,
|
||||||
|
split: None,
|
||||||
|
group: None,
|
||||||
|
order: None,
|
||||||
|
limit: None,
|
||||||
|
start: None,
|
||||||
}),
|
}),
|
||||||
Part::Graph(Graph {
|
Part::Graph(Graph {
|
||||||
dir: Dir::Out,
|
dir: Dir::Out,
|
||||||
|
expr: Fields::all(),
|
||||||
what: Table::from("person").into(),
|
what: Table::from("person").into(),
|
||||||
cond: None,
|
cond: None,
|
||||||
alias: None,
|
alias: None,
|
||||||
|
split: None,
|
||||||
|
group: None,
|
||||||
|
order: None,
|
||||||
|
limit: None,
|
||||||
|
start: None,
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
use crate::err::Error;
|
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::value::serde::ser;
|
||||||
use crate::sql::Cond;
|
use crate::sql::Cond;
|
||||||
use crate::sql::Dir;
|
use crate::sql::Dir;
|
||||||
|
@ -39,8 +45,14 @@ impl ser::Serializer for Serializer {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(super) struct SerializeGraph {
|
pub(super) struct SerializeGraph {
|
||||||
dir: Option<Dir>,
|
dir: Option<Dir>,
|
||||||
|
expr: Option<Fields>,
|
||||||
what: Option<Tables>,
|
what: Option<Tables>,
|
||||||
cond: Option<Cond>,
|
cond: Option<Cond>,
|
||||||
|
split: Option<Splits>,
|
||||||
|
group: Option<Groups>,
|
||||||
|
order: Option<Orders>,
|
||||||
|
limit: Option<Limit>,
|
||||||
|
start: Option<Start>,
|
||||||
alias: Option<Idiom>,
|
alias: Option<Idiom>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,12 +68,30 @@ impl serde::ser::SerializeStruct for SerializeGraph {
|
||||||
"dir" => {
|
"dir" => {
|
||||||
self.dir = Some(value.serialize(ser::dir::Serializer.wrap())?);
|
self.dir = Some(value.serialize(ser::dir::Serializer.wrap())?);
|
||||||
}
|
}
|
||||||
|
"expr" => {
|
||||||
|
self.expr = Some(value.serialize(ser::fields::Serializer.wrap())?);
|
||||||
|
}
|
||||||
"what" => {
|
"what" => {
|
||||||
self.what = Some(Tables(value.serialize(ser::table::vec::Serializer.wrap())?));
|
self.what = Some(Tables(value.serialize(ser::table::vec::Serializer.wrap())?));
|
||||||
}
|
}
|
||||||
"cond" => {
|
"cond" => {
|
||||||
self.cond = value.serialize(ser::cond::opt::Serializer.wrap())?;
|
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" => {
|
"alias" => {
|
||||||
self.alias = value.serialize(ser::part::vec::opt::Serializer.wrap())?.map(Idiom);
|
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> {
|
fn end(self) -> Result<Self::Ok, Error> {
|
||||||
match (self.dir, self.what) {
|
match (self.dir, self.expr, self.what) {
|
||||||
(Some(dir), Some(what)) => Ok(Graph {
|
(Some(dir), Some(expr), Some(what)) => Ok(Graph {
|
||||||
dir,
|
dir,
|
||||||
|
expr,
|
||||||
what,
|
what,
|
||||||
cond: self.cond,
|
cond: self.cond,
|
||||||
|
split: self.split,
|
||||||
|
group: self.group,
|
||||||
|
order: self.order,
|
||||||
|
limit: self.limit,
|
||||||
|
start: self.start,
|
||||||
alias: self.alias,
|
alias: self.alias,
|
||||||
}),
|
}),
|
||||||
_ => Err(Error::custom("`Graph` missing required field(s)")),
|
_ => Err(Error::custom("`Graph` missing required field(s)")),
|
||||||
|
|
Loading…
Reference in a new issue