diff --git a/query-builder/src/statements/for_loop.rs b/query-builder/src/statements/for_loop.rs index bc48ea2557..4e93c7ba34 100644 --- a/query-builder/src/statements/for_loop.rs +++ b/query-builder/src/statements/for_loop.rs @@ -62,17 +62,48 @@ impl From<&Param> for ForParam { } } +/// A helper function to create a for loop +/// ``` +/// use surreal_query_builder as surreal_orm; +/// use surreal_orm::{*, statements::{for_, select, select_value}}; +/// +/// let ref person_table = Table::from("person"); +/// let ref user_name = Field::from("user_name"); +/// +/// for_!((name in vec!["Oyelowo", "Oyedayo"]) { +/// select(All).from(person_table).where_(user_name.eq(name)); +/// select(All).from(person_table).where_(user_name.eq(name)); +/// +/// for_!((name in select_value(user_name).from_only(person_table)) { +/// select(All).from(person_table).where_(user_name.eq(name)); +/// select(All).from(person_table).where_(user_name.eq(name)); +/// }); +/// }); +/// ``` +#[macro_export] +macro_rules! for_loop { + (($param:ident in $iterable:expr) { $($stmt:expr;)+ }) => {{ + let ref $param = $crate::Param::new(stringify!($param)); + $crate::statements::for_($param).in_($iterable).block($crate::block! { + $($stmt;)+ + }) + }}; + (($param:ident IN $iterable:expr) { $($stmt:expr;)+ }) => {{ + let ref $param = $crate::Param::new(stringify!($param)); + $crate::statements::for_($param).in_($iterable).block($crate::block! { + $($stmt;)+ + }) + }}; +} +pub use for_loop as for_; + // #[macro_export] -// macro_rules! FOR { -// ($param:ident IN $iterable:expr { $($stmt:expr;)+ }) => {{ +// macro_rules! for_ { +// ($param:ident in $iterable:expr; $block:block) => {{ // let ref $param = $crate::Param::new(stringify!($param)); -// $crate::for_($param).in_($iterable).block($crate::block! { -// $($stmt;)+ -// }) +// $crate::statements::for_($param).in_($iterable).block($crate::block! { $block }) // }}; // } - - /// A helper function to create a for loop /// ``` /// use surreal_query_builder as surreal_orm; @@ -145,7 +176,7 @@ impl Buildable for ForLoopStatement { .join(", "), ); - query.push_str(" "); + query.push(' '); match &self.0.flow_type { FlowType::InIterableData(iterable) => { @@ -157,10 +188,11 @@ impl Buildable for ForLoopStatement { query.push_str(&iterable.build()); } } - query.push_str(" "); + query.push(' '); if let Some(block) = &self.0.block { query.push_str(&block.build()); } + query.push(';'); query } } @@ -212,9 +244,45 @@ impl fmt::Display for ForLoopStatement { mod tests { use super::*; use crate::{statements::{if_, select::{select, select_value}}, *}; + + #[test] + fn test_for_macro() { + let ref person_table = Table::from("person"); + let ref user_name = Field::from("user_name"); + + let for_loop = for_!((name in vec!["Oyelowo", "Oyedayo"]) { + select(All).from(person_table).where_(user_name.eq(name)); + }); + + assert_eq!( + for_loop.fine_tune_params(), + "FOR $name IN $_param_00000001 {\nSELECT * FROM person WHERE user_name = $name;\n};" + ); + assert_eq!( + for_loop.to_raw().build(), + "FOR $name IN ['Oyelowo', 'Oyedayo'] {\nSELECT * FROM person WHERE user_name = $name;\n};" + ); + } #[test] - fn test_for_in_blockx() { + fn test_for_macro_nested() { + let ref __name = Param::new("name"); + let ref person_table = Table::from("person"); + let ref user_name = Field::from("user_name"); + + let for_loop = for_!((__name in vec!["Oyelowo", "Oyedayo"]) { + select(All).from(person_table).where_(user_name.eq(__name)); + for_!((__name in vec!["Oyelowo", "Oyedayo"]) { + select(All).from(person_table).where_(user_name.eq(__name)); + }); + }); + + insta::assert_snapshot!(for_loop.fine_tune_params()); + insta::assert_snapshot!(for_loop.to_raw().build()); + } + + #[test] + fn test_for_macro_and_block_macro() { let ref person_table = Table::from("person"); let ref user_name = Field::from("user_name"); @@ -223,6 +291,10 @@ mod tests { select(All).from(person_table).where_(user_name.eq(__name)); select(All).from(person_table).where_(user_name.eq(__name)); + for_!((__moniker IN select_value(user_name).from(person_table)) { + select(All).from(person_table).where_(user_name.eq(__moniker)); + select(All).from(person_table).where_(user_name.eq(__name)); + }); for_(__name).in_(vec!["Oyelowo", "Oyedayo"]) .block(block! { @@ -243,28 +315,34 @@ mod tests { if_(__name.eq("Oyelowo")).then(6).end(); - }; - // IF (__name.eq("Oyelowo")) THEN { - // select(All).from(person_table).where_(user_name.eq(__name)); - // select(All).from(person_table).where_(user_name.eq(__name)); - // } ELSE IF (__name.eq("Oyelowo")) THEN{ - // select(All).from(person_table).where_(user_name.eq(__name)); - // select(All).from(person_table).where_(user_name.eq(__name)); - // }; - + for_!((__name in vec!["Oyelowo"]) { + select(All).from(person_table).where_(user_name.eq(__name)); + select(All).from(person_table).where_(user_name.eq(__name)); - assert_eq!( - for_loop.fine_tune_params(), - "FOR $name IN $_param_00000001 {\nSELECT * FROM person WHERE user_name = $name;\n}" - ); - assert_eq!( - for_loop.to_raw().build(), - "FOR $name IN ['Oyelowo', 'Oyedayo'] {\nSELECT * FROM person WHERE user_name = $name;\n}" - ); + for_!((__name in vec!["Oyelowo"]) { + select(All).from(person_table).where_(user_name.eq(__name)); + select(All).from(person_table).where_(user_name.eq(__name)); + + for_!((__name in vec!["Oyelowo"]) { + select(All).from(person_table).where_(user_name.eq(__name)); + select(All).from(person_table).where_(user_name.eq(__name)); + }); + + for_!((__name in vec!["Oyelowo"]) { + select(All).from(person_table).where_(user_name.eq(__name)); + select(All).from(person_table).where_(user_name.eq(__name)); + }); + + }); + }); + + insta::assert_snapshot!(for_loop.fine_tune_params()); + insta::assert_snapshot!(for_loop.to_raw().build()); } + #[test] fn test_for_in_block() { let ref __name = Param::new("name"); @@ -277,11 +355,11 @@ mod tests { assert_eq!( for_loop.fine_tune_params(), - "FOR $name IN $_param_00000001 {\nSELECT * FROM person WHERE user_name = $name;\n}" + "FOR $name IN $_param_00000001 {\nSELECT * FROM person WHERE user_name = $name;\n};" ); assert_eq!( for_loop.to_raw().build(), - "FOR $name IN ['Oyelowo', 'Oyedayo'] {\nSELECT * FROM person WHERE user_name = $name;\n}" + "FOR $name IN ['Oyelowo', 'Oyedayo'] {\nSELECT * FROM person WHERE user_name = $name;\n};" ); } @@ -300,12 +378,12 @@ mod tests { assert_eq!( for_loop.fine_tune_params(), - "FOR $name IN $_param_00000001 {\nLET $nick_name = $_param_00000002;\n\nSELECT * FROM person WHERE user_name = $nick_name;\n}" + "FOR $name IN $_param_00000001 {\nLET $nick_name = $_param_00000002;\n\nSELECT * FROM person WHERE user_name = $nick_name;\n};" ); assert_eq!( for_loop.to_raw().build(), - "FOR $name IN ['Oyelowo', 'Oyedayo'] {\nLET $nick_name = (SELECT user_name FROM ONLY person WHERE user_name = $name);\n\nSELECT * FROM person WHERE user_name = $nick_name;\n}" + "FOR $name IN ['Oyelowo', 'Oyedayo'] {\nLET $nick_name = (SELECT user_name FROM ONLY person WHERE user_name = $name);\n\nSELECT * FROM person WHERE user_name = $nick_name;\n};" ); } @@ -329,12 +407,12 @@ mod tests { assert_eq!( for_loop.fine_tune_params(), - "FOR $name IN $_param_00000001 {\nLET $__nick_name = $_param_00000002;\n\nSELECT * FROM person WHERE user_name = $__nick_name;\n}" + "FOR $name IN $_param_00000001 {\nLET $__nick_name = $_param_00000002;\n\nSELECT * FROM person WHERE user_name = $__nick_name;\n};" ); assert_eq!( for_loop.to_raw().build(), - "FOR $name IN (SELECT VALUE user_name FROM person WHERE user_name = $name) {\nLET $__nick_name = (SELECT user_name FROM ONLY person WHERE user_name = $name);\n\nSELECT * FROM person WHERE user_name = $__nick_name;\n}" + "FOR $name IN (SELECT VALUE user_name FROM person WHERE user_name = $name) {\nLET $__nick_name = (SELECT user_name FROM ONLY person WHERE user_name = $name);\n\nSELECT * FROM person WHERE user_name = $__nick_name;\n};" ); } } diff --git a/query-builder/src/statements/ifelse.rs b/query-builder/src/statements/ifelse.rs index 7b0284c508..86c7a885db 100644 --- a/query-builder/src/statements/ifelse.rs +++ b/query-builder/src/statements/ifelse.rs @@ -90,34 +90,8 @@ pub fn if_(condition: impl Conditional) -> IfStatement { IfStatement::new(condition) } -#[macro_export] -macro_rules! if_block { - (if ($condition:expr) then { $($then_body:expr;)+ } $(else if ($elif_condition:expr) then { $($elif_body:expr;)+ })* $(else { $($else_body:expr;)+ })?) => { - { - let mut __statements: ::std::vec::Vec<$crate::statements::utils::Chainable> = ::std::vec::Vec::new(); - - let if_condition = $crate::statements::if_($condition); - let if_block = $crate::block! { $($then_body;)+ }; - __statements.push(if_condition.then(if_block).into()); - - $( - let elif_condition = $crate::statements::if_($elif_condition); - let elif_block = $crate::block! { $($elif_body;)+ }; - __statements.push(elif_condition.else_if(elif_block).into()); - )* - - $( - let else_block = $crate::block! { $($else_body;)+ }; - __statements.push(else_block.into()); - )? - - $crate::statements::utils::QueryChain::from(__statements) - } - }; -} - #[derive(Debug, Clone)] -pub struct IfElseExpression(Expression); +struct IfElseExpression(Expression); impl From for IfElseExpression { fn from(value: Expression) -> Self { diff --git a/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_and_block_macro-2.snap b/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_and_block_macro-2.snap new file mode 100644 index 0000000000..d96f1b0dc7 --- /dev/null +++ b/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_and_block_macro-2.snap @@ -0,0 +1,35 @@ +--- +source: query-builder/src/statements/for_loop.rs +expression: for_loop.to_raw().build() +--- +FOR $__name IN ['Oyelowo', 'Oyedayo'] { +SELECT * FROM person WHERE user_name = $__name; + +SELECT * FROM person WHERE user_name = $__name; + +FOR $__moniker IN (SELECT VALUE user_name FROM person) { +SELECT * FROM person WHERE user_name = $__moniker; + +SELECT * FROM person WHERE user_name = $__name; +}; + +FOR $__name IN ['Oyelowo', 'Oyedayo'] { +SELECT * FROM person WHERE user_name = $__name; +}; +}; + +FOR $__name IN ['Oyelowo', 'Oyedayo'] { +SELECT * FROM person WHERE user_name = $__name; + +SELECT * FROM person WHERE user_name = $__name; +}; + +FOR $__name IN ['Oyelowo', 'Oyedayo'] { +SELECT * FROM person WHERE user_name = $__name; + +SELECT * FROM person WHERE user_name = $__name; +}; + +IF $__name = 'Oyelowo' THEN + 6 +END diff --git a/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_and_block_macro.snap b/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_and_block_macro.snap new file mode 100644 index 0000000000..0c85aaface --- /dev/null +++ b/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_and_block_macro.snap @@ -0,0 +1,35 @@ +--- +source: query-builder/src/statements/for_loop.rs +expression: for_loop.fine_tune_params() +--- +FOR $__name IN $_param_00000001 { +SELECT * FROM person WHERE user_name = $__name; + +SELECT * FROM person WHERE user_name = $__name; + +FOR $__moniker IN $_param_00000002 { +SELECT * FROM person WHERE user_name = $__moniker; + +SELECT * FROM person WHERE user_name = $__name; +}; + +FOR $__name IN $_param_00000003 { +SELECT * FROM person WHERE user_name = $__name; +}; +}; + +FOR $__name IN $_param_00000004 { +SELECT * FROM person WHERE user_name = $__name; + +SELECT * FROM person WHERE user_name = $__name; +}; + +FOR $__name IN $_param_00000005 { +SELECT * FROM person WHERE user_name = $__name; + +SELECT * FROM person WHERE user_name = $__name; +}; + +IF $__name = $_param_00000006 THEN + $_param_00000007 +END diff --git a/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_nested-2.snap b/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_nested-2.snap new file mode 100644 index 0000000000..18539938dd --- /dev/null +++ b/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_nested-2.snap @@ -0,0 +1,11 @@ +--- +source: query-builder/src/statements/for_loop.rs +expression: for_loop.to_raw().build() +--- +FOR $__name IN ['Oyelowo', 'Oyedayo'] { +SELECT * FROM person WHERE user_name = $__name; + +FOR $__name IN ['Oyelowo', 'Oyedayo'] { +SELECT * FROM person WHERE user_name = $__name; +}; +}; diff --git a/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_nested.snap b/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_nested.snap new file mode 100644 index 0000000000..2e0c23ab77 --- /dev/null +++ b/query-builder/src/statements/snapshots/surreal_query_builder__statements__for_loop__tests__for_macro_nested.snap @@ -0,0 +1,11 @@ +--- +source: query-builder/src/statements/for_loop.rs +expression: for_loop.fine_tune_params() +--- +FOR $__name IN $_param_00000001 { +SELECT * FROM person WHERE user_name = $__name; + +FOR $__name IN $_param_00000002 { +SELECT * FROM person WHERE user_name = $__name; +}; +}; diff --git a/query-builder/src/statements/utils_block.rs b/query-builder/src/statements/utils_block.rs index 6b18ef944d..a1644b85b4 100644 --- a/query-builder/src/statements/utils_block.rs +++ b/query-builder/src/statements/utils_block.rs @@ -407,7 +407,6 @@ macro_rules! block_inner { let ref $param = $crate::Param::new(stringify!($param)); let for_loop = $crate::statements::for_($param).in_($iterable).block($crate::block! { $($stmt;)+ }); - // let mut __statements: ::std::vec::Vec<$crate::statements::utils::Chainable> = ::std::vec::Vec::new(); $statements.push(for_loop.into()); $crate::block_inner!($statements; $($rest)*); }}; @@ -416,7 +415,6 @@ macro_rules! block_inner { let ref $param = $crate::Param::new(stringify!($param)); let for_loop = $crate::statements::for_($param).in_($iterable).block($crate::block! { $($stmt;)+ }); - // let mut __statements: ::std::vec::Vec<$crate::statements::utils::Chainable> = ::std::vec::Vec::new(); $statements.push(for_loop.clone().into()); $crate::block_inner!($statements; $($rest)*); }};