surrealdb_core/sql/statements/define/
namespace.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::statements::info::InfoStructure;
7use crate::sql::{Base, Ident, Strand, Value};
8
9use revision::revisioned;
10use serde::{Deserialize, Serialize};
11use std::fmt::{self, Display};
12
13#[revisioned(revision = 3)]
14#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
15#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
16#[non_exhaustive]
17pub struct DefineNamespaceStatement {
18	pub id: Option<u32>,
19	pub name: Ident,
20	pub comment: Option<Strand>,
21	#[revision(start = 2)]
22	pub if_not_exists: bool,
23	#[revision(start = 3)]
24	pub overwrite: bool,
25}
26
27impl DefineNamespaceStatement {
28	/// Process this type returning a computed simple Value
29	pub(crate) async fn compute(
30		&self,
31		ctx: &Context,
32		opt: &Options,
33		_doc: Option<&CursorDoc>,
34	) -> Result<Value, Error> {
35		// Allowed to run?
36		opt.is_allowed(Action::Edit, ResourceKind::Namespace, &Base::Root)?;
37		// Fetch the transaction
38		let txn = ctx.tx();
39		// Check if the definition exists
40		if txn.get_ns(&self.name).await.is_ok() {
41			if self.if_not_exists {
42				return Ok(Value::None);
43			} else if !self.overwrite {
44				return Err(Error::NsAlreadyExists {
45					name: self.name.to_string(),
46				});
47			}
48		}
49		// Process the statement
50		let key = crate::key::root::ns::new(&self.name);
51		txn.set(
52			key,
53			revision::to_vec(&DefineNamespaceStatement {
54				id: if self.id.is_none() {
55					Some(txn.lock().await.get_next_ns_id().await?)
56				} else {
57					None
58				},
59				// Don't persist the `IF NOT EXISTS` clause to schema
60				if_not_exists: false,
61				overwrite: false,
62				..self.clone()
63			})?,
64			None,
65		)
66		.await?;
67		// Clear the cache
68		txn.clear();
69		// Ok all good
70		Ok(Value::None)
71	}
72}
73
74impl Display for DefineNamespaceStatement {
75	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76		write!(f, "DEFINE NAMESPACE")?;
77		if self.if_not_exists {
78			write!(f, " IF NOT EXISTS")?
79		}
80		if self.overwrite {
81			write!(f, " OVERWRITE")?
82		}
83		write!(f, " {}", self.name)?;
84		if let Some(ref v) = self.comment {
85			write!(f, " COMMENT {v}")?
86		}
87		Ok(())
88	}
89}
90
91impl InfoStructure for DefineNamespaceStatement {
92	fn structure(self) -> Value {
93		Value::from(map! {
94			"name".to_string() => self.name.structure(),
95			"comment".to_string(), if let Some(v) = self.comment => v.into(),
96		})
97	}
98}