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, Permission, Strand, Value};
9
10use reblessive::tree::Stk;
11use revision::revisioned;
12use serde::{Deserialize, Serialize};
13use std::fmt::{self, Display, Write};
14
15#[revisioned(revision = 3)]
16#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, 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	#[revision(start = 3)]
27	pub overwrite: bool,
28}
29
30impl DefineParamStatement {
31	/// Process this type returning a computed simple Value
32	pub(crate) async fn compute(
33		&self,
34		stk: &mut Stk,
35		ctx: &Context,
36		opt: &Options,
37		doc: Option<&CursorDoc>,
38	) -> Result<Value, Error> {
39		// Allowed to run?
40		opt.is_allowed(Action::Edit, ResourceKind::Parameter, &Base::Db)?;
41		// Fetch the transaction
42		let txn = ctx.tx();
43		// Check if the definition exists
44		let (ns, db) = opt.ns_db()?;
45		if txn.get_db_param(ns, db, &self.name).await.is_ok() {
46			if self.if_not_exists {
47				return Ok(Value::None);
48			} else if !self.overwrite {
49				return Err(Error::PaAlreadyExists {
50					name: self.name.to_string(),
51				});
52			}
53		}
54		// Process the statement
55		let key = crate::key::database::pa::new(ns, db, &self.name);
56		txn.get_or_add_ns(ns, opt.strict).await?;
57		txn.get_or_add_db(ns, db, opt.strict).await?;
58		txn.set(
59			key,
60			revision::to_vec(&DefineParamStatement {
61				// Compute the param
62				value: self.value.compute(stk, ctx, opt, doc).await?,
63				// Don't persist the `IF NOT EXISTS` clause to schema
64				if_not_exists: false,
65				overwrite: false,
66				..self.clone()
67			})?,
68			None,
69		)
70		.await?;
71		// Clear the cache
72		txn.clear();
73		// Ok all good
74		Ok(Value::None)
75	}
76}
77
78impl Display for DefineParamStatement {
79	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80		write!(f, "DEFINE PARAM")?;
81		if self.if_not_exists {
82			write!(f, " IF NOT EXISTS")?
83		}
84		if self.overwrite {
85			write!(f, " OVERWRITE")?
86		}
87		write!(f, " ${} VALUE {}", self.name, self.value)?;
88		if let Some(ref v) = self.comment {
89			write!(f, " COMMENT {v}")?
90		}
91		let _indent = if is_pretty() {
92			Some(pretty_indent())
93		} else {
94			f.write_char(' ')?;
95			None
96		};
97		write!(f, "PERMISSIONS {}", self.permissions)?;
98		Ok(())
99	}
100}
101
102impl InfoStructure for DefineParamStatement {
103	fn structure(self) -> Value {
104		Value::from(map! {
105			"name".to_string() => self.name.structure(),
106			"value".to_string() => self.value.structure(),
107			"permissions".to_string() => self.permissions.structure(),
108			"comment".to_string(), if let Some(v) = self.comment => v.into(),
109		})
110	}
111}