2022-05-14 12:35:08 +00:00
|
|
|
use crate::ctx::Context;
|
2022-01-13 17:36:41 +00:00
|
|
|
use crate::dbs::Options;
|
2022-02-15 01:00:30 +00:00
|
|
|
use crate::dbs::Transaction;
|
2021-03-29 15:43:37 +00:00
|
|
|
use crate::err::Error;
|
2022-01-16 20:31:50 +00:00
|
|
|
use crate::sql::error::IResult;
|
2023-03-31 15:42:29 +00:00
|
|
|
use crate::sql::ident::{ident, Ident};
|
2023-03-30 10:41:44 +00:00
|
|
|
use crate::sql::serde::is_internal_serialization;
|
2022-01-13 17:36:41 +00:00
|
|
|
use crate::sql::value::Value;
|
2022-03-16 23:52:25 +00:00
|
|
|
use nom::character::complete::char;
|
2020-06-29 15:36:01 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use std::fmt;
|
2022-05-04 21:38:19 +00:00
|
|
|
use std::ops::Deref;
|
2020-06-29 15:36:01 +00:00
|
|
|
use std::str;
|
|
|
|
|
2023-03-30 10:41:44 +00:00
|
|
|
pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Param";
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Deserialize, Hash)]
|
2023-03-31 15:42:29 +00:00
|
|
|
pub struct Param(pub Ident);
|
2021-03-31 11:54:20 +00:00
|
|
|
|
2023-03-31 15:42:29 +00:00
|
|
|
impl From<Ident> for Param {
|
|
|
|
fn from(v: Ident) -> Self {
|
|
|
|
Self(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<String> for Param {
|
|
|
|
fn from(v: String) -> Self {
|
|
|
|
Self(v.into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&str> for Param {
|
|
|
|
fn from(v: &str) -> Self {
|
|
|
|
Self(v.into())
|
2022-05-04 21:38:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Deref for Param {
|
2023-03-31 15:42:29 +00:00
|
|
|
type Target = Ident;
|
2022-05-04 21:38:19 +00:00
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
2021-03-31 11:54:20 +00:00
|
|
|
}
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
|
2022-01-14 08:12:56 +00:00
|
|
|
impl Param {
|
2022-05-01 22:25:53 +00:00
|
|
|
pub(crate) async fn compute(
|
2021-03-29 15:43:37 +00:00
|
|
|
&self,
|
2022-05-14 12:35:08 +00:00
|
|
|
ctx: &Context<'_>,
|
2022-02-06 21:06:52 +00:00
|
|
|
opt: &Options,
|
2022-02-15 03:33:16 +00:00
|
|
|
txn: &Transaction,
|
2022-01-13 17:36:41 +00:00
|
|
|
doc: Option<&Value>,
|
|
|
|
) -> Result<Value, Error> {
|
2023-03-31 15:42:29 +00:00
|
|
|
// Find the variable by name
|
|
|
|
match self.as_str() {
|
|
|
|
// This is a special param
|
|
|
|
"this" | "self" => match doc {
|
|
|
|
// The base document exists
|
|
|
|
Some(v) => v.compute(ctx, opt, txn, doc).await,
|
|
|
|
// The base document does not exist
|
|
|
|
None => Ok(Value::None),
|
|
|
|
},
|
|
|
|
// This is a normal param
|
|
|
|
v => match ctx.value(v) {
|
|
|
|
// The param has been set locally
|
|
|
|
Some(v) => v.compute(ctx, opt, txn, doc).await,
|
|
|
|
// The param has not been set locally
|
|
|
|
None => {
|
|
|
|
// Clone transaction
|
|
|
|
let run = txn.clone();
|
|
|
|
// Claim transaction
|
|
|
|
let mut run = run.lock().await;
|
|
|
|
// Get the param definition
|
|
|
|
let val = run.get_pa(opt.ns(), opt.db(), v).await;
|
|
|
|
// Check if the param has been set globally
|
|
|
|
match val {
|
|
|
|
// The param has been set globally
|
|
|
|
Ok(v) => Ok(v.value),
|
|
|
|
// The param has not been set globally
|
|
|
|
Err(_) => Ok(Value::None),
|
2023-01-09 12:43:47 +00:00
|
|
|
}
|
2023-03-31 15:42:29 +00:00
|
|
|
}
|
2022-01-13 17:36:41 +00:00
|
|
|
},
|
|
|
|
}
|
2021-03-29 15:43:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-14 08:12:56 +00:00
|
|
|
impl fmt::Display for Param {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2022-05-04 21:38:19 +00:00
|
|
|
write!(f, "${}", &self.0)
|
2022-01-14 08:12:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-30 10:41:44 +00:00
|
|
|
impl Serialize for Param {
|
|
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
|
|
where
|
|
|
|
S: serde::Serializer,
|
|
|
|
{
|
|
|
|
if is_internal_serialization() {
|
|
|
|
serializer.serialize_newtype_struct(TOKEN, &self.0)
|
|
|
|
} else {
|
|
|
|
serializer.serialize_none()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:36:01 +00:00
|
|
|
pub fn param(i: &str) -> IResult<&str, Param> {
|
2022-03-16 23:52:25 +00:00
|
|
|
let (i, _) = char('$')(i)?;
|
2023-03-31 15:42:29 +00:00
|
|
|
let (i, v) = ident(i)?;
|
2022-10-17 02:13:10 +00:00
|
|
|
Ok((i, Param::from(v)))
|
|
|
|
}
|
|
|
|
|
2020-06-29 15:36:01 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
|
|
|
|
use super::*;
|
2022-01-13 17:36:41 +00:00
|
|
|
use crate::sql::test::Parse;
|
2020-06-29 15:36:01 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn param_normal() {
|
|
|
|
let sql = "$test";
|
|
|
|
let res = param(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("$test", format!("{}", out));
|
2022-01-13 17:36:41 +00:00
|
|
|
assert_eq!(out, Param::parse("$test"));
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn param_longer() {
|
|
|
|
let sql = "$test_and_deliver";
|
|
|
|
let res = param(sql);
|
|
|
|
assert!(res.is_ok());
|
|
|
|
let out = res.unwrap().1;
|
|
|
|
assert_eq!("$test_and_deliver", format!("{}", out));
|
2022-01-13 17:36:41 +00:00
|
|
|
assert_eq!(out, Param::parse("$test_and_deliver"));
|
2020-06-29 15:36:01 +00:00
|
|
|
}
|
|
|
|
}
|