parent
6e6621565d
commit
2e0093c41d
17 changed files with 270 additions and 221 deletions
|
@ -7,7 +7,7 @@ use crate::sql::comment::shouldbespace;
|
||||||
use crate::sql::common::commas;
|
use crate::sql::common::commas;
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::fmt::Fmt;
|
use crate::sql::fmt::Fmt;
|
||||||
use crate::sql::idiom::{idiom, Idiom};
|
use crate::sql::idiom::{plain as idiom, Idiom};
|
||||||
use crate::sql::operator::{assigner, Operator};
|
use crate::sql::operator::{assigner, Operator};
|
||||||
use crate::sql::table::Table;
|
use crate::sql::table::Table;
|
||||||
use crate::sql::thing::Thing;
|
use crate::sql::thing::Thing;
|
||||||
|
|
|
@ -24,7 +24,6 @@ pub fn number(i: &str) -> IResult<&str, ()> {
|
||||||
map(char('"'), |_| ()),
|
map(char('"'), |_| ()),
|
||||||
map(char('\''), |_| ()),
|
map(char('\''), |_| ()),
|
||||||
map(char(';'), |_| ()),
|
map(char(';'), |_| ()),
|
||||||
map(char('.'), |_| ()),
|
|
||||||
map(char(','), |_| ()),
|
map(char(','), |_| ()),
|
||||||
map(tag(".."), |_| ()),
|
map(tag(".."), |_| ()),
|
||||||
map(eof, |_| ()),
|
map(eof, |_| ()),
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::sql::comment::shouldbespace;
|
||||||
use crate::sql::common::commas;
|
use crate::sql::common::commas;
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::fmt::Fmt;
|
use crate::sql::fmt::Fmt;
|
||||||
use crate::sql::idiom::{idiom, Idiom};
|
use crate::sql::idiom::{plain as idiom, Idiom};
|
||||||
use nom::bytes::complete::tag_no_case;
|
use nom::bytes::complete::tag_no_case;
|
||||||
use nom::multi::separated_list1;
|
use nom::multi::separated_list1;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::sql::common::commas;
|
||||||
use crate::sql::ending::field as ending;
|
use crate::sql::ending::field as ending;
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::fmt::Fmt;
|
use crate::sql::fmt::Fmt;
|
||||||
use crate::sql::idiom::{idiom, Idiom};
|
use crate::sql::idiom::{plain as idiom, Idiom};
|
||||||
use crate::sql::part::Part;
|
use crate::sql::part::Part;
|
||||||
use crate::sql::value::{value, Value};
|
use crate::sql::value::{value, Value};
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
|
|
|
@ -265,7 +265,7 @@ pub fn function(i: &str) -> IResult<&str, Function> {
|
||||||
alt((normal, custom, script, cast))(i)
|
alt((normal, custom, script, cast))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normal(i: &str) -> IResult<&str, Function> {
|
pub fn normal(i: &str) -> IResult<&str, Function> {
|
||||||
let (i, s) = function_names(i)?;
|
let (i, s) = function_names(i)?;
|
||||||
let (i, _) = char('(')(i)?;
|
let (i, _) = char('(')(i)?;
|
||||||
let (i, _) = mightbespace(i)?;
|
let (i, _) = mightbespace(i)?;
|
||||||
|
@ -275,7 +275,7 @@ fn normal(i: &str) -> IResult<&str, Function> {
|
||||||
Ok((i, Function::Normal(s.to_string(), a)))
|
Ok((i, Function::Normal(s.to_string(), a)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn custom(i: &str) -> IResult<&str, Function> {
|
pub fn custom(i: &str) -> IResult<&str, Function> {
|
||||||
let (i, _) = tag("fn::")(i)?;
|
let (i, _) = tag("fn::")(i)?;
|
||||||
let (i, s) = take_while1(val_char)(i)?;
|
let (i, s) = take_while1(val_char)(i)?;
|
||||||
let (i, _) = char('(')(i)?;
|
let (i, _) = char('(')(i)?;
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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::idiom::{idiom, Idiom};
|
use crate::sql::idiom::{plain as idiom, Idiom};
|
||||||
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;
|
||||||
|
|
|
@ -24,14 +24,14 @@ const BACKTICK_ESC: &str = r#"\`"#;
|
||||||
pub struct Ident(pub String);
|
pub struct Ident(pub String);
|
||||||
|
|
||||||
impl From<String> for Ident {
|
impl From<String> for Ident {
|
||||||
fn from(s: String) -> Self {
|
fn from(v: String) -> Self {
|
||||||
Self(s)
|
Self(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Ident {
|
impl From<&str> for Ident {
|
||||||
fn from(i: &str) -> Self {
|
fn from(v: &str) -> Self {
|
||||||
Self::from(String::from(i))
|
Self::from(String::from(v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::sql::common::commas;
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::fmt::{fmt_separated_by, Fmt};
|
use crate::sql::fmt::{fmt_separated_by, Fmt};
|
||||||
use crate::sql::part::Next;
|
use crate::sql::part::Next;
|
||||||
use crate::sql::part::{all, field, first, graph, index, last, part, thing, Part};
|
use crate::sql::part::{all, field, first, graph, index, last, part, value, Part};
|
||||||
use crate::sql::paths::{ID, IN, OUT};
|
use crate::sql::paths::{ID, IN, OUT};
|
||||||
use crate::sql::serde::is_internal_serialization;
|
use crate::sql::serde::is_internal_serialization;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
|
@ -92,7 +92,7 @@ impl Idiom {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
.filter(|p| matches!(p, Part::Field(_) | Part::Thing(_) | Part::Graph(_)))
|
.filter(|p| matches!(p, Part::Field(_) | Part::Value(_) | Part::Graph(_)))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
@ -127,14 +127,13 @@ impl Idiom {
|
||||||
doc: Option<&Value>,
|
doc: Option<&Value>,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
match self.first() {
|
match self.first() {
|
||||||
// The first part is a thing record
|
// The starting part is a value
|
||||||
Some(Part::Thing(v)) => {
|
Some(Part::Value(v)) => {
|
||||||
// Use the thing as the document
|
v.compute(ctx, opt, txn, doc)
|
||||||
let v: Value = v.clone().into();
|
|
||||||
// Fetch the Idiom from the document
|
|
||||||
v.get(ctx, opt, txn, self.as_ref().next())
|
|
||||||
.await?
|
.await?
|
||||||
.compute(ctx, opt, txn, Some(&v))
|
.get(ctx, opt, txn, self.as_ref().next())
|
||||||
|
.await?
|
||||||
|
.compute(ctx, opt, txn, doc)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
// Otherwise use the current document
|
// Otherwise use the current document
|
||||||
|
@ -148,7 +147,7 @@ impl Idiom {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Idiom {
|
impl Display for Idiom {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
Display::fmt(
|
Display::fmt(
|
||||||
&Fmt::new(
|
&Fmt::new(
|
||||||
|
@ -178,7 +177,7 @@ impl Serialize for Idiom {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used in a DEFINE FIELD and DEFINE INDEX clauses
|
/// Used in DEFINE FIELD and DEFINE INDEX clauses
|
||||||
pub fn local(i: &str) -> IResult<&str, Idiom> {
|
pub fn local(i: &str) -> IResult<&str, Idiom> {
|
||||||
let (i, p) = first(i)?;
|
let (i, p) = first(i)?;
|
||||||
let (i, mut v) = many0(alt((all, index, field)))(i)?;
|
let (i, mut v) = many0(alt((all, index, field)))(i)?;
|
||||||
|
@ -194,35 +193,50 @@ pub fn basic(i: &str) -> IResult<&str, Idiom> {
|
||||||
Ok((i, Idiom::from(v)))
|
Ok((i, Idiom::from(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used in a $param definition
|
/// A simple idiom with one or more parts
|
||||||
pub fn param(i: &str) -> IResult<&str, Idiom> {
|
pub fn plain(i: &str) -> IResult<&str, Idiom> {
|
||||||
|
let (i, p) = alt((first, graph))(i)?;
|
||||||
|
let (i, mut v) = many0(part)(i)?;
|
||||||
|
v.insert(0, p);
|
||||||
|
Ok((i, Idiom::from(v)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A complex idiom with graph or many parts
|
||||||
|
pub fn multi(i: &str) -> IResult<&str, Idiom> {
|
||||||
|
alt((
|
||||||
|
|i| {
|
||||||
|
let (i, p) = graph(i)?;
|
||||||
|
let (i, mut v) = many0(part)(i)?;
|
||||||
|
v.insert(0, p);
|
||||||
|
Ok((i, Idiom::from(v)))
|
||||||
|
},
|
||||||
|
|i| {
|
||||||
|
let (i, p) = first(i)?;
|
||||||
|
let (i, mut v) = many1(part)(i)?;
|
||||||
|
v.insert(0, p);
|
||||||
|
Ok((i, Idiom::from(v)))
|
||||||
|
},
|
||||||
|
|i| {
|
||||||
|
let (i, p) = value(i)?;
|
||||||
|
let (i, mut v) = many1(part)(i)?;
|
||||||
|
v.insert(0, p);
|
||||||
|
Ok((i, Idiom::from(v)))
|
||||||
|
},
|
||||||
|
))(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A simple field based idiom
|
||||||
|
pub fn path(i: &str) -> IResult<&str, Idiom> {
|
||||||
let (i, p) = first(i)?;
|
let (i, p) = first(i)?;
|
||||||
let (i, mut v) = many0(part)(i)?;
|
let (i, mut v) = many0(part)(i)?;
|
||||||
v.insert(0, p);
|
v.insert(0, p);
|
||||||
Ok((i, Idiom::from(v)))
|
Ok((i, Idiom::from(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used in a RELATE statement
|
/// A full complex idiom with any number of parts
|
||||||
pub fn plain(i: &str) -> IResult<&str, Idiom> {
|
#[cfg(test)]
|
||||||
let (i, p) = first(i)?;
|
|
||||||
Ok((i, Idiom::from(vec![p])))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn idiom(i: &str) -> IResult<&str, Idiom> {
|
pub fn idiom(i: &str) -> IResult<&str, Idiom> {
|
||||||
alt((
|
alt((plain, multi))(i)
|
||||||
|i| {
|
|
||||||
let (i, p) = alt((thing, graph))(i)?;
|
|
||||||
let (i, mut v) = many1(part)(i)?;
|
|
||||||
v.insert(0, p);
|
|
||||||
Ok((i, Idiom::from(v)))
|
|
||||||
},
|
|
||||||
|i| {
|
|
||||||
let (i, p) = alt((first, graph))(i)?;
|
|
||||||
let (i, mut v) = many0(part)(i)?;
|
|
||||||
v.insert(0, p);
|
|
||||||
Ok((i, Idiom::from(v)))
|
|
||||||
},
|
|
||||||
))(i)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -232,10 +246,19 @@ mod tests {
|
||||||
use crate::sql::dir::Dir;
|
use crate::sql::dir::Dir;
|
||||||
use crate::sql::expression::Expression;
|
use crate::sql::expression::Expression;
|
||||||
use crate::sql::graph::Graph;
|
use crate::sql::graph::Graph;
|
||||||
|
use crate::sql::number::Number;
|
||||||
|
use crate::sql::param::Param;
|
||||||
use crate::sql::table::Table;
|
use crate::sql::table::Table;
|
||||||
use crate::sql::test::Parse;
|
use crate::sql::test::Parse;
|
||||||
use crate::sql::thing::Thing;
|
use crate::sql::thing::Thing;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn idiom_number() {
|
||||||
|
let sql = "13.495";
|
||||||
|
let res = idiom(sql);
|
||||||
|
assert!(res.is_err());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn idiom_normal() {
|
fn idiom_normal() {
|
||||||
let sql = "test";
|
let sql = "test";
|
||||||
|
@ -273,7 +296,7 @@ mod tests {
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let out = res.unwrap().1;
|
let out = res.unwrap().1;
|
||||||
assert_eq!("test.temp", format!("{}", out));
|
assert_eq!("test.temp", format!("{}", out));
|
||||||
assert_eq!(out, Idiom(vec![Part::from("test"), Part::from("temp"),]));
|
assert_eq!(out, Idiom(vec![Part::from("test"), Part::from("temp")]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -283,7 +306,7 @@ mod tests {
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let out = res.unwrap().1;
|
let out = res.unwrap().1;
|
||||||
assert_eq!("test.`some key`", format!("{}", out));
|
assert_eq!("test.`some key`", format!("{}", out));
|
||||||
assert_eq!(out, Idiom(vec![Part::from("test"), Part::from("some key"),]));
|
assert_eq!(out, Idiom(vec![Part::from("test"), Part::from("some key")]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -293,7 +316,7 @@ mod tests {
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let out = res.unwrap().1;
|
let out = res.unwrap().1;
|
||||||
assert_eq!("test.temp[*]", format!("{}", out));
|
assert_eq!("test.temp[*]", format!("{}", out));
|
||||||
assert_eq!(out, Idiom(vec![Part::from("test"), Part::from("temp"), Part::All,]));
|
assert_eq!(out, Idiom(vec![Part::from("test"), Part::from("temp"), Part::All]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -303,7 +326,7 @@ mod tests {
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
let out = res.unwrap().1;
|
let out = res.unwrap().1;
|
||||||
assert_eq!("test.temp[$]", format!("{}", out));
|
assert_eq!("test.temp[$]", format!("{}", out));
|
||||||
assert_eq!(out, Idiom(vec![Part::from("test"), Part::from("temp"), Part::Last,]));
|
assert_eq!(out, Idiom(vec![Part::from("test"), Part::from("temp"), Part::Last]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -331,7 +354,7 @@ mod tests {
|
||||||
Idiom(vec![
|
Idiom(vec![
|
||||||
Part::from("test"),
|
Part::from("test"),
|
||||||
Part::from("temp"),
|
Part::from("temp"),
|
||||||
Part::from(Value::from(Expression::parse("test = true"))),
|
Part::Where(Value::from(Expression::parse("test = true"))),
|
||||||
Part::from("text")
|
Part::from("text")
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
@ -349,12 +372,30 @@ mod tests {
|
||||||
Idiom(vec![
|
Idiom(vec![
|
||||||
Part::from("test"),
|
Part::from("test"),
|
||||||
Part::from("temp"),
|
Part::from("temp"),
|
||||||
Part::from(Value::from(Expression::parse("test = true"))),
|
Part::Where(Value::from(Expression::parse("test = true"))),
|
||||||
Part::from("text")
|
Part::from("text")
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn idiom_start_param_local_field() {
|
||||||
|
let sql = "$test.temporary[0].embedded";
|
||||||
|
let res = idiom(sql);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
let out = res.unwrap().1;
|
||||||
|
assert_eq!("$test.temporary[0].embedded", format!("{}", out));
|
||||||
|
assert_eq!(
|
||||||
|
out,
|
||||||
|
Idiom(vec![
|
||||||
|
Part::Value(Param::from("test").into()),
|
||||||
|
Part::from("temporary"),
|
||||||
|
Part::Index(Number::Int(0)),
|
||||||
|
Part::from("embedded"),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn idiom_start_thing_remote_traversal() {
|
fn idiom_start_thing_remote_traversal() {
|
||||||
let sql = "person:test.friend->like->person";
|
let sql = "person:test.friend->like->person";
|
||||||
|
@ -365,15 +406,15 @@ mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
out,
|
out,
|
||||||
Idiom(vec![
|
Idiom(vec![
|
||||||
Part::from(Thing::from(("person", "test"))),
|
Part::Value(Thing::from(("person", "test")).into()),
|
||||||
Part::from("friend"),
|
Part::from("friend"),
|
||||||
Part::from(Graph {
|
Part::Graph(Graph {
|
||||||
dir: Dir::Out,
|
dir: Dir::Out,
|
||||||
what: Table::from("like").into(),
|
what: Table::from("like").into(),
|
||||||
cond: None,
|
cond: None,
|
||||||
alias: None,
|
alias: None,
|
||||||
}),
|
}),
|
||||||
Part::from(Graph {
|
Part::Graph(Graph {
|
||||||
dir: Dir::Out,
|
dir: Dir::Out,
|
||||||
what: Table::from("person").into(),
|
what: Table::from("person").into(),
|
||||||
cond: None,
|
cond: None,
|
||||||
|
|
|
@ -3,10 +3,7 @@ use crate::dbs::Options;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::idiom;
|
use crate::sql::ident::{ident, Ident};
|
||||||
use crate::sql::idiom::Idiom;
|
|
||||||
use crate::sql::part::Next;
|
|
||||||
use crate::sql::part::Part;
|
|
||||||
use crate::sql::serde::is_internal_serialization;
|
use crate::sql::serde::is_internal_serialization;
|
||||||
use crate::sql::value::Value;
|
use crate::sql::value::Value;
|
||||||
use nom::character::complete::char;
|
use nom::character::complete::char;
|
||||||
|
@ -18,16 +15,28 @@ use std::str;
|
||||||
pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Param";
|
pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Param";
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Deserialize, Hash)]
|
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Deserialize, Hash)]
|
||||||
pub struct Param(pub Idiom);
|
pub struct Param(pub Ident);
|
||||||
|
|
||||||
impl From<Idiom> for Param {
|
impl From<Ident> for Param {
|
||||||
fn from(p: Idiom) -> Self {
|
fn from(v: Ident) -> Self {
|
||||||
Self(p)
|
Self(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<String> for Param {
|
||||||
|
fn from(v: String) -> Self {
|
||||||
|
Self(v.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Param {
|
||||||
|
fn from(v: &str) -> Self {
|
||||||
|
Self(v.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for Param {
|
impl Deref for Param {
|
||||||
type Target = Idiom;
|
type Target = Ident;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
@ -41,54 +50,36 @@ impl Param {
|
||||||
txn: &Transaction,
|
txn: &Transaction,
|
||||||
doc: Option<&Value>,
|
doc: Option<&Value>,
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
// Find a base variable by name
|
// Find the variable by name
|
||||||
match self.first() {
|
match self.as_str() {
|
||||||
// The first part will be a field
|
// This is a special param
|
||||||
Some(Part::Field(v)) => match v.as_str() {
|
"this" | "self" => match doc {
|
||||||
// This is a special param
|
// The base document exists
|
||||||
"this" | "self" => match doc {
|
Some(v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
// The base document exists
|
// The base document does not exist
|
||||||
Some(v) => {
|
None => Ok(Value::None),
|
||||||
// Get the path parts
|
},
|
||||||
let pth: &[Part] = self;
|
// This is a normal param
|
||||||
// Process the parameter value
|
v => match ctx.value(v) {
|
||||||
let res = v.compute(ctx, opt, txn, doc).await?;
|
// The param has been set locally
|
||||||
// Return the desired field
|
Some(v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
res.get(ctx, opt, txn, pth.next()).await
|
// The param has not been set locally
|
||||||
}
|
None => {
|
||||||
// The base document does not exist
|
// Clone transaction
|
||||||
None => Ok(Value::None),
|
let run = txn.clone();
|
||||||
},
|
// Claim transaction
|
||||||
// This is a normal param
|
let mut run = run.lock().await;
|
||||||
_ => match ctx.value(v) {
|
// Get the param definition
|
||||||
// The param has been set locally
|
let val = run.get_pa(opt.ns(), opt.db(), v).await;
|
||||||
Some(v) => {
|
// Check if the param has been set globally
|
||||||
// Get the path parts
|
match val {
|
||||||
let pth: &[Part] = self;
|
// The param has been set globally
|
||||||
// Process the parameter value
|
Ok(v) => Ok(v.value),
|
||||||
let res = v.compute(ctx, opt, txn, doc).await?;
|
// The param has not been set globally
|
||||||
// Return the desired field
|
Err(_) => Ok(Value::None),
|
||||||
res.get(ctx, opt, txn, pth.next()).await
|
}
|
||||||
}
|
}
|
||||||
// The param has not been set locally
|
|
||||||
None => {
|
|
||||||
// Clone transaction
|
|
||||||
let run = txn.clone();
|
|
||||||
// Claim transaction
|
|
||||||
let mut run = run.lock().await;
|
|
||||||
// Get the param definition
|
|
||||||
let val = run.get_pa(opt.ns(), opt.db(), v).await;
|
|
||||||
// Check if the param has been set globally
|
|
||||||
match val {
|
|
||||||
// The param has been set globally
|
|
||||||
Ok(v) => Ok(v.value),
|
|
||||||
// The param has not been set globally
|
|
||||||
Err(_) => Ok(Value::None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,13 +105,7 @@ impl Serialize for Param {
|
||||||
|
|
||||||
pub fn param(i: &str) -> IResult<&str, Param> {
|
pub fn param(i: &str) -> IResult<&str, Param> {
|
||||||
let (i, _) = char('$')(i)?;
|
let (i, _) = char('$')(i)?;
|
||||||
let (i, v) = idiom::param(i)?;
|
let (i, v) = ident(i)?;
|
||||||
Ok((i, Param::from(v)))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn plain(i: &str) -> IResult<&str, Param> {
|
|
||||||
let (i, _) = char('$')(i)?;
|
|
||||||
let (i, v) = idiom::plain(i)?;
|
|
||||||
Ok((i, Param::from(v)))
|
Ok((i, Param::from(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,14 +134,4 @@ mod tests {
|
||||||
assert_eq!("$test_and_deliver", format!("{}", out));
|
assert_eq!("$test_and_deliver", format!("{}", out));
|
||||||
assert_eq!(out, Param::parse("$test_and_deliver"));
|
assert_eq!(out, Param::parse("$test_and_deliver"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn param_embedded() {
|
|
||||||
let sql = "$test.temporary[0].embedded";
|
|
||||||
let res = param(sql);
|
|
||||||
assert!(res.is_ok());
|
|
||||||
let out = res.unwrap().1;
|
|
||||||
assert_eq!("$test.temporary[0].embedded", format!("{}", out));
|
|
||||||
assert_eq!(out, Param::parse("$test.temporary[0].embedded"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
use crate::sql::comment::shouldbespace;
|
use crate::sql::comment::shouldbespace;
|
||||||
use crate::sql::ending::ident as ending;
|
use crate::sql::ending::ident as ending;
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::graph::{graph as graph_raw, Graph};
|
use crate::sql::graph::{self, Graph};
|
||||||
use crate::sql::ident::{ident, Ident};
|
use crate::sql::ident::{self, Ident};
|
||||||
use crate::sql::idiom::Idiom;
|
use crate::sql::idiom::Idiom;
|
||||||
use crate::sql::number::{number, Number};
|
use crate::sql::number::{number, Number};
|
||||||
use crate::sql::thing::{thing as thing_raw, Thing};
|
use crate::sql::value::{self, Value};
|
||||||
use crate::sql::value::{value, Value};
|
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
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::not;
|
||||||
|
use nom::combinator::peek;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
@ -23,8 +24,8 @@ pub enum Part {
|
||||||
Field(Ident),
|
Field(Ident),
|
||||||
Index(Number),
|
Index(Number),
|
||||||
Where(Value),
|
Where(Value),
|
||||||
Thing(Thing),
|
|
||||||
Graph(Graph),
|
Graph(Graph),
|
||||||
|
Value(Value),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i32> for Part {
|
impl From<i32> for Part {
|
||||||
|
@ -45,6 +46,12 @@ impl From<usize> for Part {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<String> for Part {
|
||||||
|
fn from(v: String) -> Self {
|
||||||
|
Self::Field(v.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Number> for Part {
|
impl From<Number> for Part {
|
||||||
fn from(v: Number) -> Self {
|
fn from(v: Number) -> Self {
|
||||||
Self::Index(v)
|
Self::Index(v)
|
||||||
|
@ -63,24 +70,12 @@ impl From<Value> for Part {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Thing> for Part {
|
|
||||||
fn from(v: Thing) -> Self {
|
|
||||||
Self::Thing(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Graph> for Part {
|
impl From<Graph> for Part {
|
||||||
fn from(v: Graph) -> Self {
|
fn from(v: Graph) -> Self {
|
||||||
Self::Graph(v)
|
Self::Graph(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Part {
|
|
||||||
fn from(v: String) -> Self {
|
|
||||||
Self::Field(Ident(v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for Part {
|
impl From<&str> for Part {
|
||||||
fn from(v: &str) -> Self {
|
fn from(v: &str) -> Self {
|
||||||
match v.parse::<isize>() {
|
match v.parse::<isize>() {
|
||||||
|
@ -109,8 +104,8 @@ impl fmt::Display for Part {
|
||||||
Part::Field(v) => write!(f, ".{v}"),
|
Part::Field(v) => write!(f, ".{v}"),
|
||||||
Part::Index(v) => write!(f, "[{v}]"),
|
Part::Index(v) => write!(f, "[{v}]"),
|
||||||
Part::Where(v) => write!(f, "[WHERE {v}]"),
|
Part::Where(v) => write!(f, "[WHERE {v}]"),
|
||||||
Part::Thing(v) => write!(f, "{v}"),
|
|
||||||
Part::Graph(v) => write!(f, "{v}"),
|
Part::Graph(v) => write!(f, "{v}"),
|
||||||
|
Part::Value(v) => write!(f, "{v}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +132,8 @@ pub fn part(i: &str) -> IResult<&str, Part> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn first(i: &str) -> IResult<&str, Part> {
|
pub fn first(i: &str) -> IResult<&str, Part> {
|
||||||
let (i, v) = ident(i)?;
|
let (i, _) = peek(not(number))(i)?;
|
||||||
|
let (i, v) = ident::ident(i)?;
|
||||||
let (i, _) = ending(i)?;
|
let (i, _) = ending(i)?;
|
||||||
Ok((i, Part::Field(v)))
|
Ok((i, Part::Field(v)))
|
||||||
}
|
}
|
||||||
|
@ -175,7 +171,7 @@ pub fn index(i: &str) -> IResult<&str, Part> {
|
||||||
|
|
||||||
pub fn field(i: &str) -> IResult<&str, Part> {
|
pub fn field(i: &str) -> IResult<&str, Part> {
|
||||||
let (i, _) = char('.')(i)?;
|
let (i, _) = char('.')(i)?;
|
||||||
let (i, v) = ident(i)?;
|
let (i, v) = ident::ident(i)?;
|
||||||
let (i, _) = ending(i)?;
|
let (i, _) = ending(i)?;
|
||||||
Ok((i, Part::Field(v)))
|
Ok((i, Part::Field(v)))
|
||||||
}
|
}
|
||||||
|
@ -184,18 +180,18 @@ pub fn filter(i: &str) -> IResult<&str, Part> {
|
||||||
let (i, _) = char('[')(i)?;
|
let (i, _) = char('[')(i)?;
|
||||||
let (i, _) = alt((tag_no_case("WHERE"), tag("?")))(i)?;
|
let (i, _) = alt((tag_no_case("WHERE"), tag("?")))(i)?;
|
||||||
let (i, _) = shouldbespace(i)?;
|
let (i, _) = shouldbespace(i)?;
|
||||||
let (i, v) = value(i)?;
|
let (i, v) = value::value(i)?;
|
||||||
let (i, _) = char(']')(i)?;
|
let (i, _) = char(']')(i)?;
|
||||||
Ok((i, Part::Where(v)))
|
Ok((i, Part::Where(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn thing(i: &str) -> IResult<&str, Part> {
|
pub fn value(i: &str) -> IResult<&str, Part> {
|
||||||
let (i, v) = thing_raw(i)?;
|
let (i, v) = value::start(i)?;
|
||||||
Ok((i, Part::Thing(v)))
|
Ok((i, Part::Value(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn graph(i: &str) -> IResult<&str, Part> {
|
pub fn graph(i: &str) -> IResult<&str, Part> {
|
||||||
let (i, v) = graph_raw(i)?;
|
let (i, v) = graph::graph(i)?;
|
||||||
Ok((i, Part::Graph(v)))
|
Ok((i, Part::Graph(v)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ 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::plain as param;
|
use crate::sql::param::param;
|
||||||
use crate::sql::subquery::subquery;
|
use crate::sql::subquery::subquery;
|
||||||
use crate::sql::table::table;
|
use crate::sql::table::table;
|
||||||
use crate::sql::thing::thing;
|
use crate::sql::thing::thing;
|
||||||
|
|
|
@ -97,6 +97,29 @@ impl Value {
|
||||||
try_join_all(futs).await.map(Into::into)
|
try_join_all(futs).await.map(Into::into)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// Current path part is an edges
|
||||||
|
Value::Edges(v) => {
|
||||||
|
// Clone the thing
|
||||||
|
let val = v.clone();
|
||||||
|
// Check how many path parts are remaining
|
||||||
|
match path.len() {
|
||||||
|
// No remote embedded fields, so just return this
|
||||||
|
0 => Ok(Value::Edges(val)),
|
||||||
|
// Remote embedded field, so fetch the thing
|
||||||
|
_ => {
|
||||||
|
let stm = SelectStatement {
|
||||||
|
expr: Fields(vec![Field::All], false),
|
||||||
|
what: Values(vec![Value::from(val)]),
|
||||||
|
..SelectStatement::default()
|
||||||
|
};
|
||||||
|
stm.compute(ctx, opt, txn, None)
|
||||||
|
.await?
|
||||||
|
.first()
|
||||||
|
.get(ctx, opt, txn, path)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Current path part is a thing
|
// Current path part is a thing
|
||||||
Value::Thing(v) => {
|
Value::Thing(v) => {
|
||||||
// Clone the thing
|
// Clone the thing
|
||||||
|
|
|
@ -9,14 +9,6 @@ impl Value {
|
||||||
Some(p) => match self {
|
Some(p) => match self {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
Value::Object(v) => match p {
|
Value::Object(v) => match p {
|
||||||
Part::Thing(t) => match v.get_mut(t.to_raw().as_str()) {
|
|
||||||
Some(v) if v.is_some() => v.put(path.next(), val),
|
|
||||||
_ => {
|
|
||||||
let mut obj = Value::base();
|
|
||||||
obj.put(path.next(), val);
|
|
||||||
v.insert(t.to_raw(), obj);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Part::Graph(g) => match v.get_mut(g.to_raw().as_str()) {
|
Part::Graph(g) => match v.get_mut(g.to_raw().as_str()) {
|
||||||
Some(v) if v.is_some() => v.put(path.next(), val),
|
Some(v) if v.is_some() => v.put(path.next(), val),
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -54,8 +54,8 @@ impl ser::Serializer for Serializer {
|
||||||
"Field" => Ok(Part::Field(Ident(value.serialize(ser::string::Serializer.wrap())?))),
|
"Field" => Ok(Part::Field(Ident(value.serialize(ser::string::Serializer.wrap())?))),
|
||||||
"Index" => Ok(Part::Index(value.serialize(ser::number::Serializer.wrap())?)),
|
"Index" => Ok(Part::Index(value.serialize(ser::number::Serializer.wrap())?)),
|
||||||
"Where" => Ok(Part::Where(value.serialize(ser::value::Serializer.wrap())?)),
|
"Where" => Ok(Part::Where(value.serialize(ser::value::Serializer.wrap())?)),
|
||||||
"Thing" => Ok(Part::Thing(value.serialize(ser::thing::Serializer.wrap())?)),
|
|
||||||
"Graph" => Ok(Part::Graph(value.serialize(ser::graph::Serializer.wrap())?)),
|
"Graph" => Ok(Part::Graph(value.serialize(ser::graph::Serializer.wrap())?)),
|
||||||
|
"Value" => Ok(Part::Value(value.serialize(ser::value::Serializer.wrap())?)),
|
||||||
variant => {
|
variant => {
|
||||||
Err(Error::custom(format!("unexpected newtype variant `{name}::{variant}`")))
|
Err(Error::custom(format!("unexpected newtype variant `{name}::{variant}`")))
|
||||||
}
|
}
|
||||||
|
@ -113,17 +113,17 @@ mod tests {
|
||||||
assert_eq!(part, serialized);
|
assert_eq!(part, serialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn thing() {
|
|
||||||
let part = Part::Thing(sql::thing("foo:bar").unwrap());
|
|
||||||
let serialized = serialize_internal(|| part.serialize(Serializer.wrap())).unwrap();
|
|
||||||
assert_eq!(part, serialized);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn graph() {
|
fn graph() {
|
||||||
let part = Part::Graph(Default::default());
|
let part = Part::Graph(Default::default());
|
||||||
let serialized = serialize_internal(|| part.serialize(Serializer.wrap())).unwrap();
|
let serialized = serialize_internal(|| part.serialize(Serializer.wrap())).unwrap();
|
||||||
assert_eq!(part, serialized);
|
assert_eq!(part, serialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value() {
|
||||||
|
let part = Part::Value(sql::thing("foo:bar").unwrap().into());
|
||||||
|
let serialized = serialize_internal(|| part.serialize(Serializer.wrap())).unwrap();
|
||||||
|
assert_eq!(part, serialized);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::sql::Block;
|
||||||
use crate::sql::Datetime;
|
use crate::sql::Datetime;
|
||||||
use crate::sql::Duration;
|
use crate::sql::Duration;
|
||||||
use crate::sql::Future;
|
use crate::sql::Future;
|
||||||
|
use crate::sql::Ident;
|
||||||
use crate::sql::Idiom;
|
use crate::sql::Idiom;
|
||||||
use crate::sql::Param;
|
use crate::sql::Param;
|
||||||
use crate::sql::Regex;
|
use crate::sql::Regex;
|
||||||
|
@ -222,7 +223,7 @@ impl ser::Serializer for Serializer {
|
||||||
Ok(Value::Idiom(Idiom(value.serialize(ser::part::vec::Serializer.wrap())?)))
|
Ok(Value::Idiom(Idiom(value.serialize(ser::part::vec::Serializer.wrap())?)))
|
||||||
}
|
}
|
||||||
sql::param::TOKEN => {
|
sql::param::TOKEN => {
|
||||||
Ok(Value::Param(Param(Idiom(value.serialize(ser::part::vec::Serializer.wrap())?))))
|
Ok(Value::Param(Param(Ident(value.serialize(ser::string::Serializer.wrap())?))))
|
||||||
}
|
}
|
||||||
sql::array::TOKEN => Ok(Value::Array(Array(value.serialize(vec::Serializer.wrap())?))),
|
sql::array::TOKEN => Ok(Value::Array(Array(value.serialize(vec::Serializer.wrap())?))),
|
||||||
sql::object::TOKEN => {
|
sql::object::TOKEN => {
|
||||||
|
|
|
@ -24,15 +24,6 @@ impl Value {
|
||||||
Some(p) => match self {
|
Some(p) => match self {
|
||||||
// Current path part is an object
|
// Current path part is an object
|
||||||
Value::Object(v) => match p {
|
Value::Object(v) => match p {
|
||||||
Part::Thing(t) => match v.get_mut(t.to_raw().as_str()) {
|
|
||||||
Some(v) if v.is_some() => v.set(ctx, opt, txn, path.next(), val).await,
|
|
||||||
_ => {
|
|
||||||
let mut obj = Value::base();
|
|
||||||
obj.set(ctx, opt, txn, path.next(), val).await?;
|
|
||||||
v.insert(t.to_raw(), obj);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Part::Graph(g) => match v.get_mut(g.to_raw().as_str()) {
|
Part::Graph(g) => match v.get_mut(g.to_raw().as_str()) {
|
||||||
Some(v) if v.is_some() => v.set(ctx, opt, txn, path.next(), val).await,
|
Some(v) if v.is_some() => v.set(ctx, opt, txn, path.next(), val).await,
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -14,11 +14,11 @@ use crate::sql::edges::{edges, Edges};
|
||||||
use crate::sql::error::IResult;
|
use crate::sql::error::IResult;
|
||||||
use crate::sql::expression::{expression, Expression};
|
use crate::sql::expression::{expression, Expression};
|
||||||
use crate::sql::fmt::{Fmt, Pretty};
|
use crate::sql::fmt::{Fmt, Pretty};
|
||||||
use crate::sql::function::{function, Function};
|
use crate::sql::function::{self, function, Function};
|
||||||
use crate::sql::future::{future, Future};
|
use crate::sql::future::{future, Future};
|
||||||
use crate::sql::geometry::{geometry, Geometry};
|
use crate::sql::geometry::{geometry, Geometry};
|
||||||
use crate::sql::id::Id;
|
use crate::sql::id::Id;
|
||||||
use crate::sql::idiom::{idiom, Idiom};
|
use crate::sql::idiom::{self, Idiom};
|
||||||
use crate::sql::kind::Kind;
|
use crate::sql::kind::Kind;
|
||||||
use crate::sql::model::{model, Model};
|
use crate::sql::model::{model, Model};
|
||||||
use crate::sql::number::{number, Number};
|
use crate::sql::number::{number, Number};
|
||||||
|
@ -280,6 +280,12 @@ impl From<Expression> for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Box<Edges>> for Value {
|
||||||
|
fn from(v: Box<Edges>) -> Self {
|
||||||
|
Value::Edges(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<i8> for Value {
|
impl From<i8> for Value {
|
||||||
fn from(v: i8) -> Self {
|
fn from(v: i8) -> Self {
|
||||||
Value::Number(Number::from(v))
|
Value::Number(Number::from(v))
|
||||||
|
@ -962,8 +968,8 @@ impl Value {
|
||||||
/// Converts this Value into a field name
|
/// Converts this Value into a field name
|
||||||
pub fn to_idiom(&self) -> Idiom {
|
pub fn to_idiom(&self) -> Idiom {
|
||||||
match self {
|
match self {
|
||||||
Value::Param(v) => v.simplify(),
|
|
||||||
Value::Idiom(v) => v.simplify(),
|
Value::Idiom(v) => v.simplify(),
|
||||||
|
Value::Param(v) => v.to_raw().into(),
|
||||||
Value::Strand(v) => v.0.to_string().into(),
|
Value::Strand(v) => v.0.to_string().into(),
|
||||||
Value::Datetime(v) => v.0.to_string().into(),
|
Value::Datetime(v) => v.0.to_string().into(),
|
||||||
Value::Future(_) => "future".to_string().into(),
|
Value::Future(_) => "future".to_string().into(),
|
||||||
|
@ -1545,14 +1551,12 @@ impl ops::Div for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse any `Value` including binary expressions
|
||||||
pub fn value(i: &str) -> IResult<&str, Value> {
|
pub fn value(i: &str) -> IResult<&str, Value> {
|
||||||
alt((double, single))(i)
|
alt((map(expression, Value::from), single))(i)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn double(i: &str) -> IResult<&str, Value> {
|
|
||||||
map(expression, Value::from)(i)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse any `Value` excluding binary expressions
|
||||||
pub fn single(i: &str) -> IResult<&str, Value> {
|
pub fn single(i: &str) -> IResult<&str, Value> {
|
||||||
alt((
|
alt((
|
||||||
alt((
|
alt((
|
||||||
|
@ -1562,41 +1566,9 @@ pub fn single(i: &str) -> IResult<&str, Value> {
|
||||||
map(tag_no_case("false"), |_| Value::False),
|
map(tag_no_case("false"), |_| Value::False),
|
||||||
)),
|
)),
|
||||||
alt((
|
alt((
|
||||||
map(subquery, Value::from),
|
map(idiom::multi, Value::from),
|
||||||
map(function, Value::from),
|
map(function, Value::from),
|
||||||
map(constant, Value::from),
|
|
||||||
map(datetime, Value::from),
|
|
||||||
map(duration, Value::from),
|
|
||||||
map(geometry, Value::from),
|
|
||||||
map(future, Value::from),
|
|
||||||
map(unique, Value::from),
|
|
||||||
map(number, Value::from),
|
|
||||||
map(object, Value::from),
|
|
||||||
map(array, Value::from),
|
|
||||||
map(block, Value::from),
|
|
||||||
map(param, Value::from),
|
|
||||||
map(regex, Value::from),
|
|
||||||
map(model, Value::from),
|
|
||||||
map(idiom, Value::from),
|
|
||||||
map(range, Value::from),
|
|
||||||
map(thing, Value::from),
|
|
||||||
map(strand, Value::from),
|
|
||||||
)),
|
|
||||||
))(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn select(i: &str) -> IResult<&str, Value> {
|
|
||||||
alt((
|
|
||||||
alt((
|
|
||||||
map(tag_no_case("NONE"), |_| Value::None),
|
|
||||||
map(tag_no_case("NULL"), |_| Value::Null),
|
|
||||||
map(tag_no_case("true"), |_| Value::True),
|
|
||||||
map(tag_no_case("false"), |_| Value::False),
|
|
||||||
)),
|
|
||||||
alt((
|
|
||||||
map(expression, Value::from),
|
|
||||||
map(subquery, Value::from),
|
map(subquery, Value::from),
|
||||||
map(function, Value::from),
|
|
||||||
map(constant, Value::from),
|
map(constant, Value::from),
|
||||||
map(datetime, Value::from),
|
map(datetime, Value::from),
|
||||||
map(duration, Value::from),
|
map(duration, Value::from),
|
||||||
|
@ -1613,17 +1585,75 @@ pub fn select(i: &str) -> IResult<&str, Value> {
|
||||||
map(edges, Value::from),
|
map(edges, Value::from),
|
||||||
map(range, Value::from),
|
map(range, Value::from),
|
||||||
map(thing, Value::from),
|
map(thing, Value::from),
|
||||||
map(table, Value::from),
|
|
||||||
map(strand, Value::from),
|
map(strand, Value::from),
|
||||||
|
map(idiom::path, Value::from),
|
||||||
)),
|
)),
|
||||||
))(i)
|
))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn select(i: &str) -> IResult<&str, Value> {
|
||||||
|
alt((
|
||||||
|
alt((
|
||||||
|
map(expression, Value::from),
|
||||||
|
map(tag_no_case("NONE"), |_| Value::None),
|
||||||
|
map(tag_no_case("NULL"), |_| Value::Null),
|
||||||
|
map(tag_no_case("true"), |_| Value::True),
|
||||||
|
map(tag_no_case("false"), |_| Value::False),
|
||||||
|
)),
|
||||||
|
alt((
|
||||||
|
map(idiom::multi, Value::from),
|
||||||
|
map(function, Value::from),
|
||||||
|
map(subquery, Value::from),
|
||||||
|
map(constant, Value::from),
|
||||||
|
map(datetime, Value::from),
|
||||||
|
map(duration, Value::from),
|
||||||
|
map(geometry, Value::from),
|
||||||
|
map(future, Value::from),
|
||||||
|
map(unique, Value::from),
|
||||||
|
map(number, Value::from),
|
||||||
|
map(strand, Value::from),
|
||||||
|
map(object, Value::from),
|
||||||
|
map(array, Value::from),
|
||||||
|
map(block, Value::from),
|
||||||
|
map(param, Value::from),
|
||||||
|
map(regex, Value::from),
|
||||||
|
map(model, Value::from),
|
||||||
|
map(edges, Value::from),
|
||||||
|
map(range, Value::from),
|
||||||
|
map(thing, Value::from),
|
||||||
|
map(table, Value::from),
|
||||||
|
)),
|
||||||
|
))(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used as the starting part of a complex Idiom
|
||||||
|
pub fn start(i: &str) -> IResult<&str, Value> {
|
||||||
|
alt((
|
||||||
|
map(function::normal, Value::from),
|
||||||
|
map(function::custom, Value::from),
|
||||||
|
map(subquery, Value::from),
|
||||||
|
map(constant, Value::from),
|
||||||
|
map(datetime, Value::from),
|
||||||
|
map(duration, Value::from),
|
||||||
|
map(unique, Value::from),
|
||||||
|
map(number, Value::from),
|
||||||
|
map(strand, Value::from),
|
||||||
|
map(object, Value::from),
|
||||||
|
map(array, Value::from),
|
||||||
|
map(param, Value::from),
|
||||||
|
map(edges, Value::from),
|
||||||
|
map(thing, Value::from),
|
||||||
|
))(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used in CREATE, UPDATE, and DELETE clauses
|
||||||
pub fn what(i: &str) -> IResult<&str, Value> {
|
pub fn what(i: &str) -> IResult<&str, Value> {
|
||||||
alt((
|
alt((
|
||||||
map(subquery, Value::from),
|
|
||||||
map(function, Value::from),
|
map(function, Value::from),
|
||||||
|
map(subquery, Value::from),
|
||||||
map(constant, Value::from),
|
map(constant, Value::from),
|
||||||
|
map(datetime, Value::from),
|
||||||
|
map(duration, Value::from),
|
||||||
map(future, Value::from),
|
map(future, Value::from),
|
||||||
map(block, Value::from),
|
map(block, Value::from),
|
||||||
map(param, Value::from),
|
map(param, Value::from),
|
||||||
|
@ -1635,6 +1665,7 @@ pub fn what(i: &str) -> IResult<&str, Value> {
|
||||||
))(i)
|
))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used to parse any simple JSON-like value
|
||||||
pub fn json(i: &str) -> IResult<&str, Value> {
|
pub fn json(i: &str) -> IResult<&str, Value> {
|
||||||
alt((
|
alt((
|
||||||
map(tag_no_case("NULL"), |_| Value::Null),
|
map(tag_no_case("NULL"), |_| Value::Null),
|
||||||
|
|
Loading…
Reference in a new issue