Support FOR
statements inside code blocks (#2664)
This commit is contained in:
parent
a4856327cf
commit
c3acab4614
3 changed files with 120 additions and 5 deletions
|
@ -9,6 +9,7 @@ use crate::sql::fmt::{is_pretty, pretty_indent, Fmt, Pretty};
|
|||
use crate::sql::statements::create::{create, CreateStatement};
|
||||
use crate::sql::statements::define::{define, DefineStatement};
|
||||
use crate::sql::statements::delete::{delete, DeleteStatement};
|
||||
use crate::sql::statements::foreach::{foreach, ForeachStatement};
|
||||
use crate::sql::statements::ifelse::{ifelse, IfelseStatement};
|
||||
use crate::sql::statements::insert::{insert, InsertStatement};
|
||||
use crate::sql::statements::output::{output, OutputStatement};
|
||||
|
@ -88,6 +89,9 @@ impl Block {
|
|||
// Always errors immediately
|
||||
v.compute(&ctx, opt, txn, doc).await?;
|
||||
}
|
||||
Entry::Foreach(v) => {
|
||||
v.compute(&ctx, opt, txn, doc).await?;
|
||||
}
|
||||
Entry::Ifelse(v) => {
|
||||
v.compute(&ctx, opt, txn, doc).await?;
|
||||
}
|
||||
|
@ -210,6 +214,7 @@ pub enum Entry {
|
|||
Throw(ThrowStatement),
|
||||
Break(BreakStatement),
|
||||
Continue(ContinueStatement),
|
||||
Foreach(ForeachStatement),
|
||||
}
|
||||
|
||||
impl PartialOrd for Entry {
|
||||
|
@ -238,6 +243,7 @@ impl Entry {
|
|||
Self::Throw(v) => v.writeable(),
|
||||
Self::Break(v) => v.writeable(),
|
||||
Self::Continue(v) => v.writeable(),
|
||||
Self::Foreach(v) => v.writeable(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -260,6 +266,7 @@ impl Display for Entry {
|
|||
Self::Throw(v) => write!(f, "{v}"),
|
||||
Self::Break(v) => write!(f, "{v}"),
|
||||
Self::Continue(v) => write!(f, "{v}"),
|
||||
Self::Foreach(v) => write!(f, "{v}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -282,6 +289,7 @@ pub fn entry(i: &str) -> IResult<&str, Entry> {
|
|||
map(throw, Entry::Throw),
|
||||
map(r#break, Entry::Break),
|
||||
map(r#continue, Entry::Continue),
|
||||
map(foreach, Entry::Foreach),
|
||||
map(value, Entry::Value),
|
||||
)),
|
||||
mightbespace,
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::sql::comment::{mightbespace, shouldbespace};
|
|||
use crate::sql::error::{expect_tag_no_case, IResult};
|
||||
use crate::sql::param::{param, Param};
|
||||
use crate::sql::value::{value, Value};
|
||||
use async_recursion::async_recursion;
|
||||
use derive::Store;
|
||||
use nom::bytes::complete::tag_no_case;
|
||||
use nom::combinator::cut;
|
||||
|
@ -28,12 +29,14 @@ impl ForeachStatement {
|
|||
self.range.writeable() || self.block.writeable()
|
||||
}
|
||||
/// Process this type returning a computed simple Value
|
||||
#[cfg_attr(not(target_arch = "wasm32"), async_recursion)]
|
||||
#[cfg_attr(target_arch = "wasm32", async_recursion(?Send))]
|
||||
pub(crate) async fn compute(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
opt: &Options,
|
||||
txn: &Transaction,
|
||||
doc: Option<&CursorDoc<'_>>,
|
||||
doc: Option<&'async_recursion CursorDoc<'_>>,
|
||||
) -> Result<Value, Error> {
|
||||
// Check the loop data
|
||||
match &self.range.compute(ctx, opt, txn, doc).await? {
|
||||
|
@ -58,6 +61,7 @@ impl ForeachStatement {
|
|||
Entry::Value(v) => v.compute(&ctx, opt, txn, doc).await,
|
||||
Entry::Break(v) => v.compute(&ctx, opt, txn, doc).await,
|
||||
Entry::Continue(v) => v.compute(&ctx, opt, txn, doc).await,
|
||||
Entry::Foreach(v) => v.compute(&ctx, opt, txn, doc).await,
|
||||
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,
|
||||
|
|
|
@ -7,23 +7,23 @@ use surrealdb::err::Error;
|
|||
use surrealdb::sql::Value;
|
||||
|
||||
#[tokio::test]
|
||||
async fn foreach() -> Result<(), Error> {
|
||||
async fn foreach_simple() -> Result<(), Error> {
|
||||
let sql = "
|
||||
FOR $test in [1, 2, 3] {
|
||||
FOR $test IN [1, 2, 3] {
|
||||
IF $test == 2 {
|
||||
BREAK;
|
||||
};
|
||||
UPDATE type::thing('person', $test) SET test = $test;
|
||||
};
|
||||
SELECT * FROM person;
|
||||
FOR $test in [4, 5, 6] {
|
||||
FOR $test IN [4, 5, 6] {
|
||||
IF $test == 5 {
|
||||
CONTINUE;
|
||||
};
|
||||
UPDATE type::thing('person', $test) SET test = $test;
|
||||
};
|
||||
SELECT * FROM person;
|
||||
FOR $test in <future> { [7, 8, 9] } {
|
||||
FOR $test IN <future> { [7, 8, 9] } {
|
||||
IF $test > 8 {
|
||||
THROW 'This is an error';
|
||||
};
|
||||
|
@ -96,3 +96,106 @@ async fn foreach() -> Result<(), Error> {
|
|||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn foreach_nested() -> Result<(), Error> {
|
||||
let sql = "
|
||||
FOR $i IN [1,2,3,4,5] {
|
||||
FOR $j IN [6,7,8,9,0] {
|
||||
CREATE type::thing('person', [$i, $j]);
|
||||
}
|
||||
};
|
||||
SELECT * FROM person;
|
||||
";
|
||||
let dbs = new_ds().await?;
|
||||
let ses = Session::owner().with_ns("test").with_db("test");
|
||||
let res = &mut dbs.execute(sql, &ses, None).await?;
|
||||
assert_eq!(res.len(), 2);
|
||||
//
|
||||
let tmp = res.remove(0).result;
|
||||
assert!(tmp.is_ok());
|
||||
//
|
||||
let tmp = res.remove(0).result?;
|
||||
let val = Value::parse(
|
||||
"[
|
||||
{
|
||||
id: person:[1, 0]
|
||||
},
|
||||
{
|
||||
id: person:[1, 6]
|
||||
},
|
||||
{
|
||||
id: person:[1, 7]
|
||||
},
|
||||
{
|
||||
id: person:[1, 8]
|
||||
},
|
||||
{
|
||||
id: person:[1, 9]
|
||||
},
|
||||
{
|
||||
id: person:[2, 0]
|
||||
},
|
||||
{
|
||||
id: person:[2, 6]
|
||||
},
|
||||
{
|
||||
id: person:[2, 7]
|
||||
},
|
||||
{
|
||||
id: person:[2, 8]
|
||||
},
|
||||
{
|
||||
id: person:[2, 9]
|
||||
},
|
||||
{
|
||||
id: person:[3, 0]
|
||||
},
|
||||
{
|
||||
id: person:[3, 6]
|
||||
},
|
||||
{
|
||||
id: person:[3, 7]
|
||||
},
|
||||
{
|
||||
id: person:[3, 8]
|
||||
},
|
||||
{
|
||||
id: person:[3, 9]
|
||||
},
|
||||
{
|
||||
id: person:[4, 0]
|
||||
},
|
||||
{
|
||||
id: person:[4, 6]
|
||||
},
|
||||
{
|
||||
id: person:[4, 7]
|
||||
},
|
||||
{
|
||||
id: person:[4, 8]
|
||||
},
|
||||
{
|
||||
id: person:[4, 9]
|
||||
},
|
||||
{
|
||||
id: person:[5, 0]
|
||||
},
|
||||
{
|
||||
id: person:[5, 6]
|
||||
},
|
||||
{
|
||||
id: person:[5, 7]
|
||||
},
|
||||
{
|
||||
id: person:[5, 8]
|
||||
},
|
||||
{
|
||||
id: person:[5, 9]
|
||||
}
|
||||
]",
|
||||
);
|
||||
assert_eq!(tmp, val);
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue