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, Object, Strand, Value};
8use derive::Store;
9use revision::revisioned;
10use serde::{Deserialize, Serialize};
11use std::fmt::{self, Display};
12
13#[revisioned(revision = 2)]
14#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, 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}
24
25impl DefineNamespaceStatement {
26	/// Process this type returning a computed simple Value
27	pub(crate) async fn compute(
28		&self,
29		ctx: &Context<'_>,
30		opt: &Options,
31		_doc: Option<&CursorDoc<'_>>,
32	) -> Result<Value, Error> {
33		// Allowed to run?
34		opt.is_allowed(Action::Edit, ResourceKind::Namespace, &Base::Root)?;
35		// Process the statement
36		let key = crate::key::root::ns::new(&self.name);
37		// Claim transaction
38		let mut run = ctx.tx_lock().await;
39		// Clear the cache
40		run.clear_cache();
41		// Check if namespace already exists
42		if run.get_ns(&self.name).await.is_ok() {
43			if self.if_not_exists {
44				return Ok(Value::None);
45			} else {
46				return Err(Error::NsAlreadyExists {
47					value: self.name.to_string(),
48				});
49			}
50		}
51		if self.id.is_none() {
52			// Set the id
53			let ns = DefineNamespaceStatement {
54				id: Some(run.get_next_ns_id().await?),
55				if_not_exists: false,
56				..self.clone()
57			};
58			run.set(key, ns).await?;
59		} else {
60			run.set(
61				key,
62				DefineNamespaceStatement {
63					if_not_exists: false,
64					..self.clone()
65				},
66			)
67			.await?;
68		}
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		write!(f, " {}", self.name)?;
81		if let Some(ref v) = self.comment {
82			write!(f, " COMMENT {v}")?
83		}
84		Ok(())
85	}
86}
87
88impl InfoStructure for DefineNamespaceStatement {
89	fn structure(self) -> Value {
90		let Self {
91			name,
92			comment,
93			..
94		} = self;
95		let mut acc = Object::default();
96
97		acc.insert("name".to_string(), name.structure());
98
99		if let Some(comment) = comment {
100			acc.insert("comment".to_string(), comment.into());
101		}
102
103		Value::Object(acc)
104	}
105}