surrealdb_core/sql/statements/define/
event.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, Values};
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 DefineEventStatement {
18	pub name: Ident,
19	pub what: Ident,
20	pub when: Value,
21	pub then: Values,
22	pub comment: Option<Strand>,
23	#[revision(start = 2)]
24	pub if_not_exists: bool,
25}
26
27impl DefineEventStatement {
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::Event, &Base::Db)?;
37		// Claim transaction
38		let mut run = ctx.tx_lock().await;
39		// Clear the cache
40		run.clear_cache();
41		// Check if event already exists
42		if run.get_tb_event(opt.ns()?, opt.db()?, &self.what, &self.name).await.is_ok() {
43			if self.if_not_exists {
44				return Ok(Value::None);
45			} else {
46				return Err(Error::EvAlreadyExists {
47					value: self.name.to_string(),
48				});
49			}
50		}
51		// Process the statement
52		let key = crate::key::table::ev::new(opt.ns()?, opt.db()?, &self.what, &self.name);
53		run.add_ns(opt.ns()?, opt.strict).await?;
54		run.add_db(opt.ns()?, opt.db()?, opt.strict).await?;
55		run.add_tb(opt.ns()?, opt.db()?, &self.what, opt.strict).await?;
56		run.set(
57			key,
58			DefineEventStatement {
59				if_not_exists: false,
60				..self.clone()
61			},
62		)
63		.await?;
64		// Clear the cache
65		let key = crate::key::table::ev::prefix(opt.ns()?, opt.db()?, &self.what);
66		run.clr(key).await?;
67		// Ok all good
68		Ok(Value::None)
69	}
70}
71
72impl Display for DefineEventStatement {
73	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74		write!(f, "DEFINE EVENT",)?;
75		if self.if_not_exists {
76			write!(f, " IF NOT EXISTS")?
77		}
78		write!(f, " {} ON {} WHEN {} THEN {}", self.name, self.what, self.when, self.then)?;
79		if let Some(ref v) = self.comment {
80			write!(f, " COMMENT {v}")?
81		}
82		Ok(())
83	}
84}
85
86impl InfoStructure for DefineEventStatement {
87	fn structure(self) -> Value {
88		let Self {
89			name,
90			what,
91			when,
92			then,
93			comment,
94			..
95		} = self;
96		let mut acc = Object::default();
97
98		acc.insert("name".to_string(), name.structure());
99
100		acc.insert("what".to_string(), what.structure());
101
102		acc.insert("when".to_string(), when.structure());
103
104		acc.insert(
105			"then".to_string(),
106			Value::Array(then.0.iter().map(|v| v.to_string().into()).collect()),
107		);
108
109		if let Some(comment) = comment {
110			acc.insert("comment".to_string(), comment.into());
111		}
112
113		Value::Object(acc)
114	}
115}