Add a new SQL Block
type for multi-line statements and expressions
Closes #225 Closes #1319 Related to #247
This commit is contained in:
parent
70ec7c599e
commit
9fcf4c9419
5 changed files with 335 additions and 29 deletions
274
lib/src/sql/block.rs
Normal file
274
lib/src/sql/block.rs
Normal file
|
@ -0,0 +1,274 @@
|
||||||
|
use crate::cnf::PROTECTED_PARAM_NAMES;
|
||||||
|
use crate::ctx::Context;
|
||||||
|
use crate::dbs::Options;
|
||||||
|
use crate::dbs::Transaction;
|
||||||
|
use crate::err::Error;
|
||||||
|
use crate::sql::comment::{comment, mightbespace};
|
||||||
|
use crate::sql::common::colons;
|
||||||
|
use crate::sql::error::IResult;
|
||||||
|
use crate::sql::fmt::{is_pretty, pretty_indent, Fmt, Pretty};
|
||||||
|
use crate::sql::statements::create::{create, CreateStatement};
|
||||||
|
use crate::sql::statements::delete::{delete, DeleteStatement};
|
||||||
|
use crate::sql::statements::ifelse::{ifelse, IfelseStatement};
|
||||||
|
use crate::sql::statements::insert::{insert, InsertStatement};
|
||||||
|
use crate::sql::statements::output::{output, OutputStatement};
|
||||||
|
use crate::sql::statements::relate::{relate, RelateStatement};
|
||||||
|
use crate::sql::statements::select::{select, SelectStatement};
|
||||||
|
use crate::sql::statements::set::{set, SetStatement};
|
||||||
|
use crate::sql::statements::update::{update, UpdateStatement};
|
||||||
|
use crate::sql::value::{value, Value};
|
||||||
|
use nom::branch::alt;
|
||||||
|
use nom::character::complete::char;
|
||||||
|
use nom::combinator::map;
|
||||||
|
use nom::multi::many0;
|
||||||
|
use nom::multi::separated_list1;
|
||||||
|
use nom::sequence::delimited;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::fmt::{self, Display, Formatter, Write};
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
|
||||||
|
pub struct Block(pub Vec<Entry>);
|
||||||
|
|
||||||
|
impl Deref for Block {
|
||||||
|
type Target = Vec<Entry>;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Value> for Block {
|
||||||
|
fn from(v: Value) -> Self {
|
||||||
|
Block(vec![Entry::Value(v)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Block {
|
||||||
|
pub(crate) fn writeable(&self) -> bool {
|
||||||
|
self.iter().any(Entry::writeable)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn compute(
|
||||||
|
&self,
|
||||||
|
ctx: &Context<'_>,
|
||||||
|
opt: &Options,
|
||||||
|
txn: &Transaction,
|
||||||
|
doc: Option<&Value>,
|
||||||
|
) -> Result<Value, Error> {
|
||||||
|
// Duplicate context
|
||||||
|
let mut ctx = Context::new(ctx);
|
||||||
|
// Loop over the statements
|
||||||
|
for v in self.iter() {
|
||||||
|
match v {
|
||||||
|
Entry::Set(v) => {
|
||||||
|
// Check if the variable is a protected variable
|
||||||
|
let val = match PROTECTED_PARAM_NAMES.contains(&v.name.as_str()) {
|
||||||
|
// The variable isn't protected and can be stored
|
||||||
|
false => v.compute(&ctx, opt, txn, None).await,
|
||||||
|
// The user tried to set a protected variable
|
||||||
|
true => {
|
||||||
|
return Err(Error::InvalidParam {
|
||||||
|
name: v.name.to_owned(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}?;
|
||||||
|
// Set the parameter
|
||||||
|
ctx.add_value(v.name.to_owned(), val);
|
||||||
|
}
|
||||||
|
Entry::Ifelse(v) => {
|
||||||
|
v.compute(&ctx, opt, txn, doc).await?;
|
||||||
|
}
|
||||||
|
Entry::Select(v) => {
|
||||||
|
v.compute(&ctx, opt, txn, doc).await?;
|
||||||
|
}
|
||||||
|
Entry::Create(v) => {
|
||||||
|
v.compute(&ctx, opt, txn, doc).await?;
|
||||||
|
}
|
||||||
|
Entry::Update(v) => {
|
||||||
|
v.compute(&ctx, opt, txn, doc).await?;
|
||||||
|
}
|
||||||
|
Entry::Delete(v) => {
|
||||||
|
v.compute(&ctx, opt, txn, doc).await?;
|
||||||
|
}
|
||||||
|
Entry::Relate(v) => {
|
||||||
|
v.compute(&ctx, opt, txn, doc).await?;
|
||||||
|
}
|
||||||
|
Entry::Insert(v) => {
|
||||||
|
v.compute(&ctx, opt, txn, doc).await?;
|
||||||
|
}
|
||||||
|
Entry::Output(v) => {
|
||||||
|
return v.compute(&ctx, opt, txn, doc).await;
|
||||||
|
}
|
||||||
|
Entry::Value(v) => {
|
||||||
|
return v.compute(&ctx, opt, txn, doc).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return nothing
|
||||||
|
Ok(Value::None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Block {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
let mut f = Pretty::from(f);
|
||||||
|
match (self.len(), self.first()) {
|
||||||
|
(1, Some(Entry::Value(v))) => {
|
||||||
|
write!(f, "{{ {v} }}")
|
||||||
|
}
|
||||||
|
(l, _) => {
|
||||||
|
f.write_char('{')?;
|
||||||
|
if is_pretty() && l > 1 {
|
||||||
|
f.write_char('\n')?;
|
||||||
|
}
|
||||||
|
let indent = pretty_indent();
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
&Fmt::two_line_separated(
|
||||||
|
self.0.iter().map(|args| Fmt::new(args, |v, f| write!(f, "{};", v))),
|
||||||
|
)
|
||||||
|
)?;
|
||||||
|
drop(indent);
|
||||||
|
if is_pretty() && l > 1 {
|
||||||
|
f.write_char('\n')?;
|
||||||
|
}
|
||||||
|
f.write_char('}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn block(i: &str) -> IResult<&str, Block> {
|
||||||
|
let (i, _) = char('{')(i)?;
|
||||||
|
let (i, _) = mightbespace(i)?;
|
||||||
|
let (i, v) = separated_list1(colons, entry)(i)?;
|
||||||
|
let (i, _) = many0(alt((colons, comment)))(i)?;
|
||||||
|
let (i, _) = mightbespace(i)?;
|
||||||
|
let (i, _) = char('}')(i)?;
|
||||||
|
Ok((i, Block(v)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
|
||||||
|
pub enum Entry {
|
||||||
|
Value(Value),
|
||||||
|
Set(SetStatement),
|
||||||
|
Ifelse(IfelseStatement),
|
||||||
|
Select(SelectStatement),
|
||||||
|
Create(CreateStatement),
|
||||||
|
Update(UpdateStatement),
|
||||||
|
Delete(DeleteStatement),
|
||||||
|
Relate(RelateStatement),
|
||||||
|
Insert(InsertStatement),
|
||||||
|
Output(OutputStatement),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Entry {
|
||||||
|
#[inline]
|
||||||
|
fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Entry {
|
||||||
|
pub(crate) fn writeable(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Set(v) => v.writeable(),
|
||||||
|
Self::Value(v) => v.writeable(),
|
||||||
|
Self::Ifelse(v) => v.writeable(),
|
||||||
|
Self::Select(v) => v.writeable(),
|
||||||
|
Self::Create(v) => v.writeable(),
|
||||||
|
Self::Update(v) => v.writeable(),
|
||||||
|
Self::Delete(v) => v.writeable(),
|
||||||
|
Self::Relate(v) => v.writeable(),
|
||||||
|
Self::Insert(v) => v.writeable(),
|
||||||
|
Self::Output(v) => v.writeable(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Entry {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Set(v) => write!(f, "{v}"),
|
||||||
|
Self::Value(v) => Display::fmt(v, f),
|
||||||
|
Self::Ifelse(v) => write!(f, "{v}"),
|
||||||
|
Self::Select(v) => write!(f, "{v}"),
|
||||||
|
Self::Create(v) => write!(f, "{v}"),
|
||||||
|
Self::Update(v) => write!(f, "{v}"),
|
||||||
|
Self::Delete(v) => write!(f, "{v}"),
|
||||||
|
Self::Relate(v) => write!(f, "{v}"),
|
||||||
|
Self::Insert(v) => write!(f, "{v}"),
|
||||||
|
Self::Output(v) => write!(f, "{v}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn entry(i: &str) -> IResult<&str, Entry> {
|
||||||
|
delimited(
|
||||||
|
mightbespace,
|
||||||
|
alt((
|
||||||
|
map(set, Entry::Set),
|
||||||
|
map(output, Entry::Output),
|
||||||
|
map(ifelse, Entry::Ifelse),
|
||||||
|
map(select, Entry::Select),
|
||||||
|
map(create, Entry::Create),
|
||||||
|
map(update, Entry::Update),
|
||||||
|
map(relate, Entry::Relate),
|
||||||
|
map(delete, Entry::Delete),
|
||||||
|
map(insert, Entry::Insert),
|
||||||
|
map(value, Entry::Value),
|
||||||
|
)),
|
||||||
|
mightbespace,
|
||||||
|
)(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn block_value() {
|
||||||
|
let sql = "{ 80 }";
|
||||||
|
let res = block(sql);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
let out = res.unwrap().1;
|
||||||
|
assert_eq!(sql, format!("{}", out))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn block_ifelse() {
|
||||||
|
let sql = "{
|
||||||
|
RETURN IF true THEN
|
||||||
|
50
|
||||||
|
ELSE
|
||||||
|
40
|
||||||
|
END;
|
||||||
|
}";
|
||||||
|
let res = block(sql);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
let out = res.unwrap().1;
|
||||||
|
assert_eq!(sql, format!("{:#}", out))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn block_multiple() {
|
||||||
|
let sql = r#"{
|
||||||
|
|
||||||
|
LET $person = (SELECT * FROM person WHERE first = $first AND last = $last AND birthday = $birthday);
|
||||||
|
|
||||||
|
RETURN IF $person[0].id THEN
|
||||||
|
$person[0]
|
||||||
|
ELSE
|
||||||
|
(CREATE person SET first = $first, last = $last, birthday = $birthday)
|
||||||
|
END;
|
||||||
|
|
||||||
|
}"#;
|
||||||
|
let res = block(sql);
|
||||||
|
assert!(res.is_ok());
|
||||||
|
let out = res.unwrap().1;
|
||||||
|
assert_eq!(sql, format!("{:#}", out))
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,19 +34,17 @@ impl<I: IntoIterator<Item = T>, T: Display> Fmt<I, fn(I, &mut Formatter) -> fmt:
|
||||||
/// Formats values with a comma and a space separating them or, if pretty printing is in
|
/// Formats values with a comma and a space separating them or, if pretty printing is in
|
||||||
/// effect, a comma, a newline, and indentation.
|
/// effect, a comma, a newline, and indentation.
|
||||||
pub(crate) fn pretty_comma_separated(into_iter: I) -> Self {
|
pub(crate) fn pretty_comma_separated(into_iter: I) -> Self {
|
||||||
Self::new(
|
Self::new(into_iter, fmt_pretty_comma_separated)
|
||||||
into_iter,
|
|
||||||
if is_pretty() {
|
|
||||||
fmt_pretty_comma_separated
|
|
||||||
} else {
|
|
||||||
fmt_comma_separated
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Formats values with a new line separating them.
|
/// Formats values with a new line separating them.
|
||||||
pub(crate) fn pretty_new_line_separated(into_iter: I) -> Self {
|
pub(crate) fn one_line_separated(into_iter: I) -> Self {
|
||||||
Self::new(into_iter, fmt_new_line_separated)
|
Self::new(into_iter, fmt_one_line_separated)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Formats values with a new line separating them.
|
||||||
|
pub(crate) fn two_line_separated(into_iter: I) -> Self {
|
||||||
|
Self::new(into_iter, fmt_two_line_separated)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +54,6 @@ fn fmt_comma_separated<T: Display>(
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
for (i, v) in into_iter.into_iter().enumerate() {
|
for (i, v) in into_iter.into_iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
// This comma goes after the item formatted in the last iteration.
|
|
||||||
f.write_str(", ")?;
|
f.write_str(", ")?;
|
||||||
}
|
}
|
||||||
Display::fmt(&v, f)?;
|
Display::fmt(&v, f)?;
|
||||||
|
@ -70,23 +67,24 @@ fn fmt_pretty_comma_separated<T: Display>(
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
for (i, v) in into_iter.into_iter().enumerate() {
|
for (i, v) in into_iter.into_iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
// We don't need a space after the comma if we are going to have a newline.
|
if is_pretty() {
|
||||||
f.write_char(',')?;
|
f.write_char(',')?;
|
||||||
pretty_sequence_item();
|
pretty_sequence_item();
|
||||||
|
} else {
|
||||||
|
f.write_str(", ")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Display::fmt(&v, f)?;
|
Display::fmt(&v, f)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fmt_new_line_separated<T: Display>(
|
fn fmt_one_line_separated<T: Display>(
|
||||||
into_iter: impl IntoIterator<Item = T>,
|
into_iter: impl IntoIterator<Item = T>,
|
||||||
f: &mut Formatter,
|
f: &mut Formatter,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
for (i, v) in into_iter.into_iter().enumerate() {
|
for (i, v) in into_iter.into_iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
// One of the few cases where the raw string data depends on is pretty i.e. we don't
|
|
||||||
// need a space after the comma if we are going to have a newline.
|
|
||||||
if is_pretty() {
|
if is_pretty() {
|
||||||
pretty_sequence_item();
|
pretty_sequence_item();
|
||||||
} else {
|
} else {
|
||||||
|
@ -98,6 +96,25 @@ fn fmt_new_line_separated<T: Display>(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fmt_two_line_separated<T: Display>(
|
||||||
|
into_iter: impl IntoIterator<Item = T>,
|
||||||
|
f: &mut Formatter,
|
||||||
|
) -> fmt::Result {
|
||||||
|
for (i, v) in into_iter.into_iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
if is_pretty() {
|
||||||
|
f.write_char('\n')?;
|
||||||
|
pretty_sequence_item();
|
||||||
|
} else {
|
||||||
|
f.write_char('\n')?;
|
||||||
|
f.write_char('\n')?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Display::fmt(&v, f)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a formatting function that joins iterators with an arbitrary separator.
|
/// Creates a formatting function that joins iterators with an arbitrary separator.
|
||||||
pub fn fmt_separated_by<T: Display, II: IntoIterator<Item = T>>(
|
pub fn fmt_separated_by<T: Display, II: IntoIterator<Item = T>>(
|
||||||
separator: impl Display,
|
separator: impl Display,
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
pub(crate) mod algorithm;
|
pub(crate) mod algorithm;
|
||||||
pub(crate) mod array;
|
pub(crate) mod array;
|
||||||
pub(crate) mod base;
|
pub(crate) mod base;
|
||||||
|
pub(crate) mod block;
|
||||||
pub(crate) mod comment;
|
pub(crate) mod comment;
|
||||||
pub(crate) mod common;
|
pub(crate) mod common;
|
||||||
pub(crate) mod cond;
|
pub(crate) mod cond;
|
||||||
|
@ -70,6 +71,7 @@ pub use self::parser::*;
|
||||||
pub use self::algorithm::Algorithm;
|
pub use self::algorithm::Algorithm;
|
||||||
pub use self::array::Array;
|
pub use self::array::Array;
|
||||||
pub use self::base::Base;
|
pub use self::base::Base;
|
||||||
|
pub use self::block::Block;
|
||||||
pub use self::cond::Cond;
|
pub use self::cond::Cond;
|
||||||
pub use self::data::Data;
|
pub use self::data::Data;
|
||||||
pub use self::datetime::Datetime;
|
pub use self::datetime::Datetime;
|
||||||
|
|
|
@ -50,9 +50,7 @@ impl Deref for Statements {
|
||||||
impl fmt::Display for Statements {
|
impl fmt::Display for Statements {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
Display::fmt(
|
Display::fmt(
|
||||||
&Fmt::pretty_new_line_separated(
|
&Fmt::one_line_separated(self.0.iter().map(|v| Fmt::new(v, |v, f| write!(f, "{v};")))),
|
||||||
self.0.iter().map(|v| Fmt::new(v, |v, f| write!(f, "{v};"))),
|
|
||||||
),
|
|
||||||
f,
|
f,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::dbs::Options;
|
||||||
use crate::dbs::Transaction;
|
use crate::dbs::Transaction;
|
||||||
use crate::err::Error;
|
use crate::err::Error;
|
||||||
use crate::sql::array::{array, Array};
|
use crate::sql::array::{array, Array};
|
||||||
|
use crate::sql::block::{block, Block};
|
||||||
use crate::sql::common::commas;
|
use crate::sql::common::commas;
|
||||||
use crate::sql::constant::{constant, Constant};
|
use crate::sql::constant::{constant, Constant};
|
||||||
use crate::sql::datetime::{datetime, Datetime};
|
use crate::sql::datetime::{datetime, Datetime};
|
||||||
|
@ -116,6 +117,7 @@ pub enum Value {
|
||||||
Thing(Thing),
|
Thing(Thing),
|
||||||
Model(Model),
|
Model(Model),
|
||||||
Regex(Regex),
|
Regex(Regex),
|
||||||
|
Block(Box<Block>),
|
||||||
Range(Box<Range>),
|
Range(Box<Range>),
|
||||||
Edges(Box<Edges>),
|
Edges(Box<Edges>),
|
||||||
Future(Box<Future>),
|
Future(Box<Future>),
|
||||||
|
@ -239,6 +241,12 @@ impl From<Constant> for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Block> for Value {
|
||||||
|
fn from(v: Block) -> Self {
|
||||||
|
Value::Block(Box::new(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Range> for Value {
|
impl From<Range> for Value {
|
||||||
fn from(v: Range) -> Self {
|
fn from(v: Range) -> Self {
|
||||||
Value::Range(Box::new(v))
|
Value::Range(Box::new(v))
|
||||||
|
@ -1314,6 +1322,7 @@ impl fmt::Display for Value {
|
||||||
Value::Thing(v) => write!(f, "{v}"),
|
Value::Thing(v) => write!(f, "{v}"),
|
||||||
Value::Model(v) => write!(f, "{v}"),
|
Value::Model(v) => write!(f, "{v}"),
|
||||||
Value::Regex(v) => write!(f, "{v}"),
|
Value::Regex(v) => write!(f, "{v}"),
|
||||||
|
Value::Block(v) => write!(f, "{v}"),
|
||||||
Value::Range(v) => write!(f, "{v}"),
|
Value::Range(v) => write!(f, "{v}"),
|
||||||
Value::Edges(v) => write!(f, "{v}"),
|
Value::Edges(v) => write!(f, "{v}"),
|
||||||
Value::Future(v) => write!(f, "{v}"),
|
Value::Future(v) => write!(f, "{v}"),
|
||||||
|
@ -1328,9 +1337,10 @@ impl fmt::Display for Value {
|
||||||
impl Value {
|
impl Value {
|
||||||
pub(crate) fn writeable(&self) -> bool {
|
pub(crate) fn writeable(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Value::Array(v) => v.iter().any(|v| v.writeable()),
|
Value::Block(v) => v.writeable(),
|
||||||
|
Value::Array(v) => v.iter().any(Value::writeable),
|
||||||
Value::Object(v) => v.iter().any(|(_, v)| v.writeable()),
|
Value::Object(v) => v.iter().any(|(_, v)| v.writeable()),
|
||||||
Value::Function(v) => v.args().iter().any(|v| v.writeable()),
|
Value::Function(v) => v.args().iter().any(Value::writeable),
|
||||||
Value::Subquery(v) => v.writeable(),
|
Value::Subquery(v) => v.writeable(),
|
||||||
Value::Expression(v) => v.l.writeable() || v.r.writeable(),
|
Value::Expression(v) => v.l.writeable() || v.r.writeable(),
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -1352,6 +1362,7 @@ impl Value {
|
||||||
Value::True => Ok(Value::True),
|
Value::True => Ok(Value::True),
|
||||||
Value::False => Ok(Value::False),
|
Value::False => Ok(Value::False),
|
||||||
Value::Thing(v) => v.compute(ctx, opt, txn, doc).await,
|
Value::Thing(v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
|
Value::Block(v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Value::Range(v) => v.compute(ctx, opt, txn, doc).await,
|
Value::Range(v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Value::Param(v) => v.compute(ctx, opt, txn, doc).await,
|
Value::Param(v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
Value::Idiom(v) => v.compute(ctx, opt, txn, doc).await,
|
Value::Idiom(v) => v.compute(ctx, opt, txn, doc).await,
|
||||||
|
@ -1392,13 +1403,14 @@ impl Serialize for Value {
|
||||||
Value::Thing(v) => s.serialize_newtype_variant("Value", 15, "Thing", v),
|
Value::Thing(v) => s.serialize_newtype_variant("Value", 15, "Thing", v),
|
||||||
Value::Model(v) => s.serialize_newtype_variant("Value", 16, "Model", v),
|
Value::Model(v) => s.serialize_newtype_variant("Value", 16, "Model", v),
|
||||||
Value::Regex(v) => s.serialize_newtype_variant("Value", 17, "Regex", v),
|
Value::Regex(v) => s.serialize_newtype_variant("Value", 17, "Regex", v),
|
||||||
Value::Range(v) => s.serialize_newtype_variant("Value", 18, "Range", v),
|
Value::Block(v) => s.serialize_newtype_variant("Value", 18, "Block", v),
|
||||||
Value::Edges(v) => s.serialize_newtype_variant("Value", 19, "Edges", v),
|
Value::Range(v) => s.serialize_newtype_variant("Value", 19, "Range", v),
|
||||||
Value::Future(v) => s.serialize_newtype_variant("Value", 20, "Future", v),
|
Value::Edges(v) => s.serialize_newtype_variant("Value", 20, "Edges", v),
|
||||||
Value::Constant(v) => s.serialize_newtype_variant("Value", 21, "Constant", v),
|
Value::Future(v) => s.serialize_newtype_variant("Value", 21, "Future", v),
|
||||||
Value::Function(v) => s.serialize_newtype_variant("Value", 22, "Function", v),
|
Value::Constant(v) => s.serialize_newtype_variant("Value", 22, "Constant", v),
|
||||||
Value::Subquery(v) => s.serialize_newtype_variant("Value", 23, "Subquery", v),
|
Value::Function(v) => s.serialize_newtype_variant("Value", 23, "Function", v),
|
||||||
Value::Expression(v) => s.serialize_newtype_variant("Value", 24, "Expression", v),
|
Value::Subquery(v) => s.serialize_newtype_variant("Value", 24, "Subquery", v),
|
||||||
|
Value::Expression(v) => s.serialize_newtype_variant("Value", 25, "Expression", v),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match self {
|
match self {
|
||||||
|
@ -1498,6 +1510,7 @@ pub fn single(i: &str) -> IResult<&str, Value> {
|
||||||
map(number, Value::from),
|
map(number, Value::from),
|
||||||
map(object, Value::from),
|
map(object, Value::from),
|
||||||
map(array, Value::from),
|
map(array, Value::from),
|
||||||
|
map(block, Value::from),
|
||||||
map(param, Value::from),
|
map(param, Value::from),
|
||||||
map(regex, Value::from),
|
map(regex, Value::from),
|
||||||
map(model, Value::from),
|
map(model, Value::from),
|
||||||
|
@ -1530,6 +1543,7 @@ pub fn select(i: &str) -> IResult<&str, Value> {
|
||||||
map(number, Value::from),
|
map(number, Value::from),
|
||||||
map(object, Value::from),
|
map(object, Value::from),
|
||||||
map(array, Value::from),
|
map(array, Value::from),
|
||||||
|
map(block, Value::from),
|
||||||
map(param, Value::from),
|
map(param, Value::from),
|
||||||
map(regex, Value::from),
|
map(regex, Value::from),
|
||||||
map(model, Value::from),
|
map(model, Value::from),
|
||||||
|
@ -1548,6 +1562,7 @@ pub fn what(i: &str) -> IResult<&str, Value> {
|
||||||
map(function, Value::from),
|
map(function, Value::from),
|
||||||
map(constant, Value::from),
|
map(constant, Value::from),
|
||||||
map(future, Value::from),
|
map(future, Value::from),
|
||||||
|
map(block, Value::from),
|
||||||
map(param, Value::from),
|
map(param, Value::from),
|
||||||
map(model, Value::from),
|
map(model, Value::from),
|
||||||
map(edges, Value::from),
|
map(edges, Value::from),
|
||||||
|
|
Loading…
Reference in a new issue