Separate Future into standalone type

This commit is contained in:
Tobie Morgan Hitchcock 2022-10-31 23:12:41 +00:00
parent ff65ef56fc
commit 426fce00a8
7 changed files with 92 additions and 49 deletions

View file

@ -1,7 +0,0 @@
use crate::ctx::Context;
use crate::err::Error;
use crate::sql::value::Value;
pub fn run(_: &Context, expr: Value) -> Result<Value, Error> {
Ok(expr)
}

View file

@ -8,7 +8,6 @@ pub mod cast;
pub mod count;
pub mod crypto;
pub mod duration;
pub mod future;
pub mod geo;
pub mod http;
pub mod is;

View file

@ -308,14 +308,14 @@ impl Datastore {
/// use surrealdb::Datastore;
/// use surrealdb::Error;
/// use surrealdb::Session;
/// use surrealdb::sql::Function;
/// use surrealdb::sql::Future;
/// use surrealdb::sql::Value;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Error> {
/// let ds = Datastore::new("memory").await?;
/// let ses = Session::for_kv();
/// let val = Value::Function(Box::new(Function::Future(Value::True)));
/// let val = Value::Future(Box::new(Future(Value::True)));
/// let res = ds.compute(val, &ses, None, false).await?;
/// Ok(())
/// }

View file

@ -19,7 +19,6 @@ use std::fmt;
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
pub enum Function {
Future(Value),
Cast(String, Value),
Normal(String, Vec<Value>),
Script(Script, Vec<Value>),
@ -116,13 +115,6 @@ impl Function {
let opt = &opt.dive(1)?;
// Process the function type
match self {
Self::Future(v) => match opt.futures {
true => {
let v = v.compute(ctx, opt, txn, doc).await?;
fnc::future::run(ctx, v)
}
false => Ok(self.to_owned().into()),
},
Self::Cast(s, x) => {
let v = x.compute(ctx, opt, txn, doc).await?;
fnc::cast::run(ctx, s, v)
@ -158,7 +150,6 @@ impl Function {
impl fmt::Display for Function {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Future(ref e) => write!(f, "<future> {{ {} }}", e),
Self::Cast(ref s, ref e) => write!(f, "<{}> {}", s, e),
Self::Script(ref s, ref e) => {
write!(f, "function({}) {{{}}}", Fmt::comma_separated(e), s)
@ -169,7 +160,7 @@ impl fmt::Display for Function {
}
pub fn function(i: &str) -> IResult<&str, Function> {
alt((normal, script, future, cast))(i)
alt((normal, script, cast))(i)
}
fn normal(i: &str) -> IResult<&str, Function> {
@ -195,19 +186,6 @@ fn script(i: &str) -> IResult<&str, Function> {
Ok((i, Function::Script(v, a)))
}
fn future(i: &str) -> IResult<&str, Function> {
let (i, _) = char('<')(i)?;
let (i, _) = tag("future")(i)?;
let (i, _) = char('>')(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('{')(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = value(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('}')(i)?;
Ok((i, Function::Future(v)))
}
fn cast(i: &str) -> IResult<&str, Function> {
let (i, _) = char('<')(i)?;
let (i, s) = function_casts(i)?;
@ -478,7 +456,6 @@ fn function_type(i: &str) -> IResult<&str, &str> {
mod tests {
use super::*;
use crate::sql::expression::Expression;
use crate::sql::test::Parse;
#[test]
@ -531,16 +508,6 @@ mod tests {
assert_eq!(out, Function::Cast(String::from("string"), 1.2345.into()));
}
#[test]
fn function_future_expression() {
let sql = "<future> { 1.2345 + 5.4321 }";
let res = function(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!("<future> { 1.2345 + 5.4321 }", format!("{}", out));
assert_eq!(out, Function::Future(Value::from(Expression::parse("1.2345 + 5.4321"))));
}
#[test]
fn function_script_expression() {
let sql = "function() { return this.tags.filter(t => { return t.length > 3; }); }";

68
lib/src/sql/future.rs Normal file
View file

@ -0,0 +1,68 @@
use crate::ctx::Context;
use crate::dbs::Options;
use crate::dbs::Transaction;
use crate::err::Error;
use crate::sql::comment::mightbespace;
use crate::sql::error::IResult;
use crate::sql::value::{value, Value};
use nom::bytes::complete::tag;
use nom::character::complete::char;
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
pub struct Future(pub Value);
impl Future {
pub(crate) async fn compute(
&self,
ctx: &Context<'_>,
opt: &Options,
txn: &Transaction,
doc: Option<&Value>,
) -> Result<Value, Error> {
// Prevent long future chains
let opt = &opt.dive(1)?;
// Process the future if enabled
match opt.futures {
true => self.0.compute(ctx, opt, txn, doc).await?.ok(),
false => Ok(self.clone().into()),
}
}
}
impl fmt::Display for Future {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<future> {{ {} }}", self.0)
}
}
pub fn future(i: &str) -> IResult<&str, Future> {
let (i, _) = char('<')(i)?;
let (i, _) = tag("future")(i)?;
let (i, _) = char('>')(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('{')(i)?;
let (i, _) = mightbespace(i)?;
let (i, v) = value(i)?;
let (i, _) = mightbespace(i)?;
let (i, _) = char('}')(i)?;
Ok((i, Future(v)))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::sql::expression::Expression;
use crate::sql::test::Parse;
#[test]
fn future_expression() {
let sql = "<future> { 1.2345 + 5.4321 }";
let res = future(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!("<future> { 1.2345 + 5.4321 }", format!("{}", out));
assert_eq!(out, Future(Value::from(Expression::parse("1.2345 + 5.4321"))));
}
}

View file

@ -18,6 +18,7 @@ pub(crate) mod fetch;
pub(crate) mod field;
pub(crate) mod fmt;
pub(crate) mod function;
pub(crate) mod future;
pub(crate) mod geometry;
pub(crate) mod graph;
pub(crate) mod group;
@ -79,6 +80,7 @@ pub use self::fetch::Fetchs;
pub use self::field::Field;
pub use self::field::Fields;
pub use self::function::Function;
pub use self::future::Future;
pub use self::geometry::Geometry;
pub use self::graph::Graph;
pub use self::group::Group;

View file

@ -14,6 +14,7 @@ use crate::sql::error::IResult;
use crate::sql::expression::{expression, Expression};
use crate::sql::fmt::Fmt;
use crate::sql::function::{function, Function};
use crate::sql::future::{future, Future};
use crate::sql::geometry::{geometry, Geometry};
use crate::sql::id::Id;
use crate::sql::idiom::{idiom, Idiom};
@ -117,6 +118,7 @@ pub enum Value {
Regex(Regex),
Range(Box<Range>),
Edges(Box<Edges>),
Future(Box<Future>),
Constant(Constant),
Function(Box<Function>),
Subquery(Box<Subquery>),
@ -255,6 +257,12 @@ impl From<Edges> for Value {
}
}
impl From<Future> for Value {
fn from(v: Future) -> Self {
Value::Future(Box::new(v))
}
}
impl From<Function> for Value {
fn from(v: Function) -> Self {
Value::Function(Box::new(v))
@ -861,8 +869,8 @@ impl Value {
Value::Idiom(v) => v.simplify(),
Value::Strand(v) => v.0.to_string().into(),
Value::Datetime(v) => v.0.to_string().into(),
Value::Future(_) => "fn::future".to_string().into(),
Value::Function(v) => match v.as_ref() {
Function::Future(_) => "fn::future".to_string().into(),
Function::Script(_, _) => "fn::script".to_string().into(),
Function::Normal(f, _) => f.to_string().into(),
Function::Cast(_, v) => v.to_idiom(),
@ -1234,6 +1242,7 @@ impl fmt::Display for Value {
Value::Regex(v) => write!(f, "{}", v),
Value::Range(v) => write!(f, "{}", v),
Value::Edges(v) => write!(f, "{}", v),
Value::Future(v) => write!(f, "{}", v),
Value::Constant(v) => write!(f, "{}", v),
Value::Function(v) => write!(f, "{}", v),
Value::Subquery(v) => write!(f, "{}", v),
@ -1273,6 +1282,7 @@ impl Value {
Value::Idiom(v) => v.compute(ctx, opt, txn, doc).await,
Value::Array(v) => v.compute(ctx, opt, txn, doc).await,
Value::Object(v) => v.compute(ctx, opt, txn, doc).await,
Value::Future(v) => v.compute(ctx, opt, txn, doc).await,
Value::Constant(v) => v.compute(ctx, opt, txn, doc).await,
Value::Function(v) => v.compute(ctx, opt, txn, doc).await,
Value::Subquery(v) => v.compute(ctx, opt, txn, doc).await,
@ -1309,10 +1319,11 @@ impl Serialize for Value {
Value::Regex(v) => s.serialize_newtype_variant("Value", 17, "Regex", v),
Value::Range(v) => s.serialize_newtype_variant("Value", 18, "Range", v),
Value::Edges(v) => s.serialize_newtype_variant("Value", 19, "Edges", v),
Value::Constant(v) => s.serialize_newtype_variant("Value", 20, "Constant", v),
Value::Function(v) => s.serialize_newtype_variant("Value", 21, "Function", v),
Value::Subquery(v) => s.serialize_newtype_variant("Value", 22, "Subquery", v),
Value::Expression(v) => s.serialize_newtype_variant("Value", 23, "Expression", v),
Value::Future(v) => s.serialize_newtype_variant("Value", 20, "Future", v),
Value::Constant(v) => s.serialize_newtype_variant("Value", 21, "Constant", v),
Value::Function(v) => s.serialize_newtype_variant("Value", 22, "Function", v),
Value::Subquery(v) => s.serialize_newtype_variant("Value", 23, "Subquery", v),
Value::Expression(v) => s.serialize_newtype_variant("Value", 24, "Expression", v),
}
} else {
match self {
@ -1407,6 +1418,7 @@ pub fn single(i: &str) -> IResult<&str, Value> {
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),
@ -1438,6 +1450,7 @@ pub fn select(i: &str) -> IResult<&str, Value> {
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),
@ -1459,6 +1472,7 @@ pub fn what(i: &str) -> IResult<&str, Value> {
map(subquery, Value::from),
map(function, Value::from),
map(constant, Value::from),
map(future, Value::from),
map(param, Value::from),
map(model, Value::from),
map(edges, Value::from),