From 426fce00a8b38a0beecc19a2071004e9f45e9ad6 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Mon, 31 Oct 2022 23:12:41 +0000 Subject: [PATCH] Separate Future into standalone type --- lib/src/fnc/future.rs | 7 ---- lib/src/fnc/mod.rs | 1 - lib/src/kvs/ds.rs | 4 +-- lib/src/sql/function.rs | 35 +------------------- lib/src/sql/future.rs | 68 ++++++++++++++++++++++++++++++++++++++ lib/src/sql/mod.rs | 2 ++ lib/src/sql/value/value.rs | 24 +++++++++++--- 7 files changed, 92 insertions(+), 49 deletions(-) delete mode 100644 lib/src/fnc/future.rs create mode 100644 lib/src/sql/future.rs diff --git a/lib/src/fnc/future.rs b/lib/src/fnc/future.rs deleted file mode 100644 index 74116707..00000000 --- a/lib/src/fnc/future.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::ctx::Context; -use crate::err::Error; -use crate::sql::value::Value; - -pub fn run(_: &Context, expr: Value) -> Result { - Ok(expr) -} diff --git a/lib/src/fnc/mod.rs b/lib/src/fnc/mod.rs index ca3053bf..284c61f9 100644 --- a/lib/src/fnc/mod.rs +++ b/lib/src/fnc/mod.rs @@ -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; diff --git a/lib/src/kvs/ds.rs b/lib/src/kvs/ds.rs index 45fcccbc..979e79ed 100644 --- a/lib/src/kvs/ds.rs +++ b/lib/src/kvs/ds.rs @@ -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(()) /// } diff --git a/lib/src/sql/function.rs b/lib/src/sql/function.rs index 6d41955a..c5b87174 100644 --- a/lib/src/sql/function.rs +++ b/lib/src/sql/function.rs @@ -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), Script(Script, Vec), @@ -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, " {{ {} }}", 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 = " { 1.2345 + 5.4321 }"; - let res = function(sql); - assert!(res.is_ok()); - let out = res.unwrap().1; - assert_eq!(" { 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; }); }"; diff --git a/lib/src/sql/future.rs b/lib/src/sql/future.rs new file mode 100644 index 00000000..13cf9c98 --- /dev/null +++ b/lib/src/sql/future.rs @@ -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 { + // 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, " {{ {} }}", 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 = " { 1.2345 + 5.4321 }"; + let res = future(sql); + assert!(res.is_ok()); + let out = res.unwrap().1; + assert_eq!(" { 1.2345 + 5.4321 }", format!("{}", out)); + assert_eq!(out, Future(Value::from(Expression::parse("1.2345 + 5.4321")))); + } +} diff --git a/lib/src/sql/mod.rs b/lib/src/sql/mod.rs index 4fe6e69b..506d2783 100644 --- a/lib/src/sql/mod.rs +++ b/lib/src/sql/mod.rs @@ -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; diff --git a/lib/src/sql/value/value.rs b/lib/src/sql/value/value.rs index c2013b0b..c1a895b1 100644 --- a/lib/src/sql/value/value.rs +++ b/lib/src/sql/value/value.rs @@ -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), Edges(Box), + Future(Box), Constant(Constant), Function(Box), Subquery(Box), @@ -255,6 +257,12 @@ impl From for Value { } } +impl From for Value { + fn from(v: Future) -> Self { + Value::Future(Box::new(v)) + } +} + impl From 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),