2021-03-29 15:43:37 +00:00
|
|
|
use crate::ctx::Context;
|
2023-07-06 14:57:42 +00:00
|
|
|
use crate::dbs::{Options, Transaction};
|
|
|
|
use crate::doc::CursorDoc;
|
2021-03-29 15:43:37 +00:00
|
|
|
use crate::err::Error;
|
2023-05-10 02:08:09 +00:00
|
|
|
use crate::sql::common::{closeparentheses, openparentheses};
|
2023-02-20 14:24:37 +00:00
|
|
|
use crate::sql::ending::subquery as ending;
|
2022-01-16 20:31:50 +00:00
|
|
|
use crate::sql::error::IResult;
|
2020-06-29 15:36:01 +00:00
|
|
|
use crate::sql::statements::create::{create, CreateStatement};
|
2023-08-23 16:05:50 +00:00
|
|
|
use crate::sql::statements::define::{define, DefineStatement};
|
2020-06-29 15:36:01 +00:00
|
|
|
use crate::sql::statements::delete::{delete, DeleteStatement};
|
|
|
|
use crate::sql::statements::ifelse::{ifelse, IfelseStatement};
|
|
|
|
use crate::sql::statements::insert::{insert, InsertStatement};
|
2023-02-19 19:41:20 +00:00
|
|
|
use crate::sql::statements::output::{output, OutputStatement};
|
2020-06-29 15:36:01 +00:00
|
|
|
use crate::sql::statements::relate::{relate, RelateStatement};
|
2023-08-23 16:05:50 +00:00
|
|
|
use crate::sql::statements::remove::{remove, RemoveStatement};
|
2020-06-29 15:36:01 +00:00
|
|
|
use crate::sql::statements::select::{select, SelectStatement};
|
|
|
|
use crate::sql::statements::update::{update, UpdateStatement};
|
2022-01-13 17:36:41 +00:00
|
|
|
use crate::sql::value::{value, Value};
|
2020-06-29 15:36:01 +00:00
|
|
|
use nom::branch::alt;
|
2023-08-29 10:50:00 +00:00
|
|
|
use nom::combinator::{cut, map};
|
2023-08-17 18:03:46 +00:00
|
|
|
use revision::revisioned;
|
2020-06-29 15:36:01 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
2021-03-29 15:43:37 +00:00
|
|
|
use std::cmp::Ordering;
|
2022-10-04 21:51:18 +00:00
|
|
|
use std::fmt::{self, Display, Formatter};
|
2020-06-29 15:36:01 +00:00
|
|
|
|
2023-03-30 10:41:44 +00:00
|
|
|
pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Subquery";
|
|
|
|
|
2023-04-29 20:50:25 +00:00
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Hash)]
|
|
|
|
#[serde(rename = "$surrealdb::private::sql::Subquery")]
|
2023-08-17 18:03:46 +00:00
|
|
|
#[revisioned(revision = 1)]
|
2020-06-29 15:36:01 +00:00
|
|
|
pub enum Subquery {
|
2022-01-13 17:36:41 +00:00
|
|
|
Value(Value),
|
2020-06-29 15:36:01 +00:00
|
|
|
Ifelse(IfelseStatement),
|
2023-02-19 19:41:20 +00:00
|
|
|
Output(OutputStatement),
|
2022-05-13 20:46:56 +00:00
|
|
|
Select(SelectStatement),
|
|
|
|
Create(CreateStatement),
|
|
|
|
Update(UpdateStatement),
|
|
|
|
Delete(DeleteStatement),
|
|
|
|
Relate(RelateStatement),
|
|
|
|
Insert(InsertStatement),
|
2023-08-23 16:05:50 +00:00
|
|
|
Define(DefineStatement),
|
|
|
|
Remove(RemoveStatement),
|
2023-04-29 20:50:25 +00:00
|
|
|
// Add new variants here
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
|
2021-03-29 15:43:37 +00:00
|
|
|
impl PartialOrd for Subquery {
|
|
|
|
#[inline]
|
|
|
|
fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
|
2022-03-23 11:56:39 +00:00
|
|
|
None
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-14 08:12:56 +00:00
|
|
|
impl Subquery {
|
2023-05-09 22:17:29 +00:00
|
|
|
/// Check if we require a writeable transaction
|
2022-05-14 21:30:49 +00:00
|
|
|
pub(crate) fn writeable(&self) -> bool {
|
|
|
|
match self {
|
2022-10-04 21:51:18 +00:00
|
|
|
Self::Value(v) => v.writeable(),
|
|
|
|
Self::Ifelse(v) => v.writeable(),
|
2023-02-19 19:41:20 +00:00
|
|
|
Self::Output(v) => v.writeable(),
|
2022-10-04 21:51:18 +00:00
|
|
|
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(),
|
2023-08-23 16:05:50 +00:00
|
|
|
Self::Define(v) => v.writeable(),
|
|
|
|
Self::Remove(v) => v.writeable(),
|
2022-05-14 21:30:49 +00:00
|
|
|
}
|
|
|
|
}
|
2023-05-09 22:17:29 +00:00
|
|
|
/// Process this type returning a computed simple Value
|
2023-07-06 14:57:42 +00:00
|
|
|
pub(crate) async fn compute(
|
|
|
|
&self,
|
|
|
|
ctx: &Context<'_>,
|
|
|
|
opt: &Options,
|
|
|
|
txn: &Transaction,
|
|
|
|
doc: Option<&CursorDoc<'_>>,
|
|
|
|
) -> Result<Value, Error> {
|
2022-10-06 16:35:03 +00:00
|
|
|
// Process the subquery
|
2021-03-29 15:43:37 +00:00
|
|
|
match self {
|
2023-07-06 14:57:42 +00:00
|
|
|
Self::Value(ref v) => v.compute(ctx, opt, txn, doc).await,
|
|
|
|
Self::Ifelse(ref v) => v.compute(ctx, opt, txn, doc).await,
|
|
|
|
Self::Output(ref v) => v.compute(ctx, opt, txn, doc).await,
|
2023-08-23 16:05:50 +00:00
|
|
|
Self::Define(ref v) => v.compute(ctx, opt, txn, doc).await,
|
|
|
|
Self::Remove(ref v) => v.compute(ctx, opt, txn, doc).await,
|
2022-10-04 21:51:18 +00:00
|
|
|
Self::Select(ref v) => {
|
2023-02-19 15:45:50 +00:00
|
|
|
// Is this a single output?
|
|
|
|
let one = v.single();
|
2022-01-13 17:36:41 +00:00
|
|
|
// Duplicate context
|
2023-07-06 14:57:42 +00:00
|
|
|
let mut ctx = Context::new(ctx);
|
2022-01-13 17:36:41 +00:00
|
|
|
// Add parent document
|
2023-07-06 14:57:42 +00:00
|
|
|
if let Some(doc) = doc {
|
|
|
|
ctx.add_value("parent", doc.doc.as_ref());
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-01-13 17:36:41 +00:00
|
|
|
// Process subquery
|
2023-07-06 14:57:42 +00:00
|
|
|
match v.compute(&ctx, opt, txn, doc).await? {
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is a single record result
|
|
|
|
Value::Array(mut a) if one => match a.len() {
|
|
|
|
// There was at least one result
|
|
|
|
v if v > 0 => Ok(a.remove(0)),
|
|
|
|
// There were no results
|
|
|
|
_ => Ok(Value::None),
|
2022-01-13 17:36:41 +00:00
|
|
|
},
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is standard query result
|
|
|
|
v => Ok(v),
|
2022-01-13 17:36:41 +00:00
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-10-04 21:51:18 +00:00
|
|
|
Self::Create(ref v) => {
|
2023-02-19 15:45:50 +00:00
|
|
|
// Is this a single output?
|
|
|
|
let one = v.single();
|
2022-01-13 17:36:41 +00:00
|
|
|
// Duplicate context
|
2023-07-06 14:57:42 +00:00
|
|
|
let mut ctx = Context::new(ctx);
|
2022-01-13 17:36:41 +00:00
|
|
|
// Add parent document
|
2023-07-06 14:57:42 +00:00
|
|
|
if let Some(doc) = doc {
|
|
|
|
ctx.add_value("parent", doc.doc.as_ref());
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-01-13 17:36:41 +00:00
|
|
|
// Process subquery
|
2023-07-06 14:57:42 +00:00
|
|
|
match v.compute(&ctx, opt, txn, doc).await? {
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is a single record result
|
|
|
|
Value::Array(mut a) if one => match a.len() {
|
|
|
|
// There was at least one result
|
|
|
|
v if v > 0 => Ok(a.remove(0)),
|
|
|
|
// There were no results
|
|
|
|
_ => Ok(Value::None),
|
2022-01-13 17:36:41 +00:00
|
|
|
},
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is standard query result
|
2022-01-13 17:36:41 +00:00
|
|
|
v => Ok(v),
|
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-10-04 21:51:18 +00:00
|
|
|
Self::Update(ref v) => {
|
2023-02-19 15:45:50 +00:00
|
|
|
// Is this a single output?
|
|
|
|
let one = v.single();
|
2022-01-13 17:36:41 +00:00
|
|
|
// Duplicate context
|
2023-07-06 14:57:42 +00:00
|
|
|
let mut ctx = Context::new(ctx);
|
2022-01-13 17:36:41 +00:00
|
|
|
// Add parent document
|
2023-07-06 14:57:42 +00:00
|
|
|
if let Some(doc) = doc {
|
|
|
|
ctx.add_value("parent", doc.doc.as_ref());
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-01-13 17:36:41 +00:00
|
|
|
// Process subquery
|
2023-07-06 14:57:42 +00:00
|
|
|
match v.compute(&ctx, opt, txn, doc).await? {
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is a single record result
|
|
|
|
Value::Array(mut a) if one => match a.len() {
|
|
|
|
// There was at least one result
|
|
|
|
v if v > 0 => Ok(a.remove(0)),
|
|
|
|
// There were no results
|
|
|
|
_ => Ok(Value::None),
|
2022-01-13 17:36:41 +00:00
|
|
|
},
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is standard query result
|
2022-01-13 17:36:41 +00:00
|
|
|
v => Ok(v),
|
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-10-04 21:51:18 +00:00
|
|
|
Self::Delete(ref v) => {
|
2023-02-19 15:45:50 +00:00
|
|
|
// Is this a single output?
|
|
|
|
let one = v.single();
|
2022-01-13 17:36:41 +00:00
|
|
|
// Duplicate context
|
2023-07-06 14:57:42 +00:00
|
|
|
let mut ctx = Context::new(ctx);
|
2022-01-13 17:36:41 +00:00
|
|
|
// Add parent document
|
2023-07-06 14:57:42 +00:00
|
|
|
if let Some(doc) = doc {
|
|
|
|
ctx.add_value("parent", doc.doc.as_ref());
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-01-13 17:36:41 +00:00
|
|
|
// Process subquery
|
2023-07-06 14:57:42 +00:00
|
|
|
match v.compute(&ctx, opt, txn, doc).await? {
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is a single record result
|
|
|
|
Value::Array(mut a) if one => match a.len() {
|
|
|
|
// There was at least one result
|
|
|
|
v if v > 0 => Ok(a.remove(0)),
|
|
|
|
// There were no results
|
|
|
|
_ => Ok(Value::None),
|
2022-01-13 17:36:41 +00:00
|
|
|
},
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is standard query result
|
2022-01-13 17:36:41 +00:00
|
|
|
v => Ok(v),
|
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-10-04 21:51:18 +00:00
|
|
|
Self::Relate(ref v) => {
|
2023-02-19 15:45:50 +00:00
|
|
|
// Is this a single output?
|
|
|
|
let one = v.single();
|
2022-01-13 17:36:41 +00:00
|
|
|
// Duplicate context
|
2023-07-06 14:57:42 +00:00
|
|
|
let mut ctx = Context::new(ctx);
|
2022-01-13 17:36:41 +00:00
|
|
|
// Add parent document
|
2023-07-06 14:57:42 +00:00
|
|
|
if let Some(doc) = doc {
|
|
|
|
ctx.add_value("parent", doc.doc.as_ref());
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-01-13 17:36:41 +00:00
|
|
|
// Process subquery
|
2023-07-06 14:57:42 +00:00
|
|
|
match v.compute(&ctx, opt, txn, doc).await? {
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is a single record result
|
|
|
|
Value::Array(mut a) if one => match a.len() {
|
|
|
|
// There was at least one result
|
|
|
|
v if v > 0 => Ok(a.remove(0)),
|
|
|
|
// There were no results
|
|
|
|
_ => Ok(Value::None),
|
2022-01-13 17:36:41 +00:00
|
|
|
},
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is standard query result
|
2022-01-13 17:36:41 +00:00
|
|
|
v => Ok(v),
|
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-10-04 21:51:18 +00:00
|
|
|
Self::Insert(ref v) => {
|
2023-02-19 15:45:50 +00:00
|
|
|
// Is this a single output?
|
|
|
|
let one = v.single();
|
2022-01-13 17:36:41 +00:00
|
|
|
// Duplicate context
|
2023-07-06 14:57:42 +00:00
|
|
|
let mut ctx = Context::new(ctx);
|
2022-01-13 17:36:41 +00:00
|
|
|
// Add parent document
|
2023-07-06 14:57:42 +00:00
|
|
|
if let Some(doc) = doc {
|
|
|
|
ctx.add_value("parent", doc.doc.as_ref());
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
2022-01-13 17:36:41 +00:00
|
|
|
// Process subquery
|
2023-07-06 14:57:42 +00:00
|
|
|
match v.compute(&ctx, opt, txn, doc).await? {
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is a single record result
|
|
|
|
Value::Array(mut a) if one => match a.len() {
|
|
|
|
// There was at least one result
|
|
|
|
v if v > 0 => Ok(a.remove(0)),
|
|
|
|
// There were no results
|
|
|
|
_ => Ok(Value::None),
|
2022-01-13 17:36:41 +00:00
|
|
|
},
|
2023-02-19 15:45:50 +00:00
|
|
|
// This is standard query result
|
2022-01-13 17:36:41 +00:00
|
|
|
v => Ok(v),
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-04 21:51:18 +00:00
|
|
|
impl Display for Subquery {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
2022-01-14 08:12:56 +00:00
|
|
|
match self {
|
2023-02-03 11:47:07 +00:00
|
|
|
Self::Value(v) => write!(f, "({v})"),
|
2023-02-19 19:41:20 +00:00
|
|
|
Self::Output(v) => write!(f, "({v})"),
|
2023-02-03 11:47:07 +00:00
|
|
|
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})"),
|
2023-08-23 16:05:50 +00:00
|
|
|
Self::Define(v) => write!(f, "({v})"),
|
|
|
|
Self::Remove(v) => write!(f, "({v})"),
|
2022-10-04 21:51:18 +00:00
|
|
|
Self::Ifelse(v) => Display::fmt(v, f),
|
2022-01-14 08:12:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:36:01 +00:00
|
|
|
pub fn subquery(i: &str) -> IResult<&str, Subquery> {
|
2023-02-20 14:24:37 +00:00
|
|
|
alt((subquery_ifelse, subquery_other, subquery_value))(i)
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn subquery_ifelse(i: &str) -> IResult<&str, Subquery> {
|
2022-03-04 16:01:32 +00:00
|
|
|
let (i, v) = map(ifelse, Subquery::Ifelse)(i)?;
|
2020-06-29 15:36:01 +00:00
|
|
|
Ok((i, v))
|
|
|
|
}
|
|
|
|
|
2023-02-20 14:24:37 +00:00
|
|
|
fn subquery_value(i: &str) -> IResult<&str, Subquery> {
|
2023-05-10 02:08:09 +00:00
|
|
|
let (i, _) = openparentheses(i)?;
|
2023-02-20 14:24:37 +00:00
|
|
|
let (i, v) = map(value, Subquery::Value)(i)?;
|
2023-08-29 10:50:00 +00:00
|
|
|
let (i, _) = cut(closeparentheses)(i)?;
|
2023-02-20 14:24:37 +00:00
|
|
|
Ok((i, v))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn subquery_other(i: &str) -> IResult<&str, Subquery> {
|
2023-09-04 18:52:32 +00:00
|
|
|
let _diving = crate::sql::parser::depth::dive()?;
|
2023-02-20 14:24:37 +00:00
|
|
|
alt((
|
|
|
|
|i| {
|
2023-05-10 02:08:09 +00:00
|
|
|
let (i, _) = openparentheses(i)?;
|
2023-02-20 14:24:37 +00:00
|
|
|
let (i, v) = subquery_inner(i)?;
|
2023-08-29 10:50:00 +00:00
|
|
|
let (i, _) = cut(closeparentheses)(i)?;
|
2023-02-20 14:24:37 +00:00
|
|
|
Ok((i, v))
|
|
|
|
},
|
|
|
|
|i| {
|
|
|
|
let (i, v) = subquery_inner(i)?;
|
|
|
|
let (i, _) = ending(i)?;
|
|
|
|
Ok((i, v))
|
|
|
|
},
|
|
|
|
))(i)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn subquery_inner(i: &str) -> IResult<&str, Subquery> {
|
|
|
|
alt((
|
2023-02-19 19:41:20 +00:00
|
|
|
map(output, Subquery::Output),
|
2022-05-13 20:46:56 +00:00
|
|
|
map(select, Subquery::Select),
|
|
|
|
map(create, Subquery::Create),
|
|
|
|
map(update, Subquery::Update),
|
|
|
|
map(delete, Subquery::Delete),
|
|
|
|
map(relate, Subquery::Relate),
|
|
|
|
map(insert, Subquery::Insert),
|
2023-08-23 16:05:50 +00:00
|
|
|
map(define, Subquery::Define),
|
|
|
|
map(remove, Subquery::Remove),
|
2023-02-20 14:24:37 +00:00
|
|
|
))(i)
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
2021-05-22 18:18:35 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn subquery_expression_statement() {
|
|
|
|
let sql = "(1 + 2 + 3)";
|
|
|
|
let res = subquery(sql);
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("(1 + 2 + 3)", format!("{}", out))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn subquery_ifelse_statement() {
|
|
|
|
let sql = "IF true THEN false END";
|
|
|
|
let res = subquery(sql);
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("IF true THEN false END", format!("{}", out))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn subquery_select_statement() {
|
|
|
|
let sql = "(SELECT * FROM test)";
|
|
|
|
let res = subquery(sql);
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("(SELECT * FROM test)", format!("{}", out))
|
|
|
|
}
|
2023-08-23 16:05:50 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn subquery_define_statement() {
|
|
|
|
let sql = "(DEFINE EVENT foo ON bar WHEN $event = 'CREATE' THEN (CREATE x SET y = 1))";
|
|
|
|
let res = subquery(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!(
|
|
|
|
"(DEFINE EVENT foo ON bar WHEN $event = 'CREATE' THEN (CREATE x SET y = 1))",
|
|
|
|
format!("{}", out)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn subquery_remove_statement() {
|
|
|
|
let sql = "(REMOVE EVENT foo_event ON foo)";
|
|
|
|
let res = subquery(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("(REMOVE EVENT foo_event ON foo)", format!("{}", out))
|
|
|
|
}
|
2021-05-22 18:18:35 +00:00
|
|
|
}
|