surrealdb_core/expr/
param.rs1use std::ops::Deref;
2use std::{fmt, str};
3
4use anyhow::{Result, bail};
5use reblessive::tree::Stk;
6use revision::revisioned;
7use serde::{Deserialize, Serialize};
8
9use super::FlowResultExt as _;
10use crate::ctx::Context;
11use crate::dbs::Options;
12use crate::doc::CursorDoc;
13use crate::err::Error;
14use crate::expr::Permission;
15use crate::expr::escape::EscapeKwFreeIdent;
16use crate::expr::ident::Ident;
17use crate::iam::Action;
18use crate::val::{Strand, Value};
19
20#[revisioned(revision = 1)]
21#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize, Hash)]
22pub struct Param(String);
23
24impl Param {
25 pub fn new(str: String) -> Option<Self> {
30 if str.contains('\0') {
31 return None;
32 }
33 Some(Self(str))
34 }
35
36 pub unsafe fn new_unchecked(str: String) -> Self {
41 Self(str)
42 }
43
44 pub fn ident(self) -> Ident {
47 unsafe { Ident::new_unchecked(self.0) }
49 }
50}
51
52impl From<Ident> for Param {
53 fn from(v: Ident) -> Self {
54 Self(v.to_string())
55 }
56}
57
58impl From<Strand> for Param {
59 fn from(v: Strand) -> Self {
60 Self(v.into_string())
61 }
62}
63
64impl Deref for Param {
65 type Target = str;
66 fn deref(&self) -> &Self::Target {
67 self.0.as_str()
68 }
69}
70
71impl Param {
72 pub(crate) async fn compute(
74 &self,
75 stk: &mut Stk,
76 ctx: &Context,
77 opt: &Options,
78 doc: Option<&CursorDoc>,
79 ) -> Result<Value> {
80 match self.0.as_str() {
82 "this" | "self" => match doc {
84 Some(v) => Ok(v.doc.as_ref().clone()),
86 None => Ok(Value::None),
88 },
89 v => match ctx.value(v) {
91 Some(v) => Ok(v.clone()),
93 None => {
95 opt.valid_for_db()?;
97 let (ns, db) = ctx.expect_ns_db_ids(opt).await?;
99 let val = ctx.tx().get_db_param(ns, db, v).await;
100 let val = match val {
102 Ok(x) => x,
103 Err(e) => {
104 if matches!(e.downcast_ref(), Some(Error::PaNotFound { .. })) {
105 return Ok(Value::None);
106 } else {
107 return Err(e);
108 }
109 }
110 };
111
112 if opt.check_perms(Action::View)? {
113 match &val.permissions {
114 Permission::Full => (),
115 Permission::None => {
116 bail!(Error::ParamPermissions {
117 name: v.to_owned(),
118 })
119 }
120 Permission::Specific(e) => {
121 let opt = &opt.new_with_perms(false);
123 if !stk
125 .run(|stk| e.compute(stk, ctx, opt, doc))
126 .await
127 .catch_return()?
128 .is_truthy()
129 {
130 bail!(Error::ParamPermissions {
131 name: v.to_owned(),
132 });
133 }
134 }
135 }
136 }
137 Ok(val.value.clone())
139 }
140 },
141 }
142 }
143}
144
145impl fmt::Display for Param {
146 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147 write!(f, "${}", EscapeKwFreeIdent(&self.0))
148 }
149}