surrealdb_core/sql/statements/define/
param.rs

1use crate::ctx::Context;
2use crate::dbs::Options;
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::iam::{Action, ResourceKind};
6use crate::sql::fmt::{is_pretty, pretty_indent};
7use crate::sql::statements::info::InfoStructure;
8use crate::sql::{Base, Ident, Object, Permission, Strand, Value};
9use derive::Store;
10use reblessive::tree::Stk;
11use revision::revisioned;
12use serde::{Deserialize, Serialize};
13use std::fmt::{self, Display, Write};
14
15#[revisioned(revision = 2)]
16#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
17#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
18#[non_exhaustive]
19pub struct DefineParamStatement {
20	pub name: Ident,
21	pub value: Value,
22	pub comment: Option<Strand>,
23	pub permissions: Permission,
24	#[revision(start = 2)]
25	pub if_not_exists: bool,
26}
27
28impl DefineParamStatement {
29	/// Process this type returning a computed simple Value
30	pub(crate) async fn compute(
31		&self,
32		stk: &mut Stk,
33		ctx: &Context<'_>,
34		opt: &Options,
35		doc: Option<&CursorDoc<'_>>,
36	) -> Result<Value, Error> {
37		// Allowed to run?
38		opt.is_allowed(Action::Edit, ResourceKind::Parameter, &Base::Db)?;
39		// Claim transaction
40		let mut run = ctx.tx_lock().await;
41		// Clear the cache
42		run.clear_cache();
43		// Check if param already exists
44		if run.get_db_param(opt.ns()?, opt.db()?, &self.name).await.is_ok() {
45			if self.if_not_exists {
46				return Ok(Value::None);
47			} else {
48				return Err(Error::PaAlreadyExists {
49					value: self.name.to_string(),
50				});
51			}
52		}
53		// Process the statement
54		let key = crate::key::database::pa::new(opt.ns()?, opt.db()?, &self.name);
55		run.add_ns(opt.ns()?, opt.strict).await?;
56		run.add_db(opt.ns()?, opt.db()?, opt.strict).await?;
57		run.set(
58			key,
59			DefineParamStatement {
60				// Compute the param
61				value: self.value.compute(stk, ctx, opt, doc).await?,
62				// Don't persist the "IF NOT EXISTS" clause to schema
63				if_not_exists: false,
64				..self.clone()
65			},
66		)
67		.await?;
68		// Ok all good
69		Ok(Value::None)
70	}
71}
72
73impl Display for DefineParamStatement {
74	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75		write!(f, "DEFINE PARAM")?;
76		if self.if_not_exists {
77			write!(f, " IF NOT EXISTS")?
78		}
79		write!(f, " ${} VALUE {}", self.name, self.value)?;
80		if let Some(ref v) = self.comment {
81			write!(f, " COMMENT {v}")?
82		}
83		let _indent = if is_pretty() {
84			Some(pretty_indent())
85		} else {
86			f.write_char(' ')?;
87			None
88		};
89		write!(f, "PERMISSIONS {}", self.permissions)?;
90		Ok(())
91	}
92}
93
94impl InfoStructure for DefineParamStatement {
95	fn structure(self) -> Value {
96		let Self {
97			name,
98			value,
99			comment,
100			permissions,
101			..
102		} = self;
103		let mut acc = Object::default();
104
105		acc.insert("name".to_string(), name.structure());
106
107		acc.insert("value".to_string(), value.structure());
108
109		if let Some(comment) = comment {
110			acc.insert("comment".to_string(), comment.into());
111		}
112
113		acc.insert("permissions".to_string(), permissions.structure());
114
115		Value::Object(acc)
116	}
117}