surrealdb_core/sql/statements/define/
model.rs1use 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::{
8 fmt::{is_pretty, pretty_indent},
9 Base, Ident, Object, Permission, Strand, Value,
10};
11use derive::Store;
12use revision::revisioned;
13use serde::{Deserialize, Serialize};
14use std::fmt::{self, Write};
15
16#[revisioned(revision = 2)]
17#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
18#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
19#[non_exhaustive]
20pub struct DefineModelStatement {
21 pub hash: String,
22 pub name: Ident,
23 pub version: String,
24 pub comment: Option<Strand>,
25 pub permissions: Permission,
26 #[revision(start = 2)]
27 pub if_not_exists: bool,
28}
29
30impl fmt::Display for DefineModelStatement {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 write!(f, "DEFINE MODEL")?;
33 if self.if_not_exists {
34 write!(f, " IF NOT EXISTS")?
35 }
36 write!(f, " ml::{}<{}>", self.name, self.version)?;
37 if let Some(comment) = self.comment.as_ref() {
38 write!(f, " COMMENT {}", comment)?;
39 }
40 let _indent = if is_pretty() {
41 Some(pretty_indent())
42 } else {
43 f.write_char(' ')?;
44 None
45 };
46 write!(f, "PERMISSIONS {}", self.permissions)?;
47 Ok(())
48 }
49}
50
51impl DefineModelStatement {
52 pub(crate) async fn compute(
54 &self,
55 ctx: &Context<'_>,
56 opt: &Options,
57 _doc: Option<&CursorDoc<'_>>,
58 ) -> Result<Value, Error> {
59 opt.is_allowed(Action::Edit, ResourceKind::Model, &Base::Db)?;
61 let mut run = ctx.tx_lock().await;
63 run.clear_cache();
65 if run.get_db_model(opt.ns()?, opt.db()?, &self.name, &self.version).await.is_ok() {
67 if self.if_not_exists {
68 return Ok(Value::None);
69 } else {
70 return Err(Error::MlAlreadyExists {
71 value: self.name.to_string(),
72 });
73 }
74 }
75 let key = crate::key::database::ml::new(opt.ns()?, opt.db()?, &self.name, &self.version);
77 run.add_ns(opt.ns()?, opt.strict).await?;
78 run.add_db(opt.ns()?, opt.db()?, opt.strict).await?;
79 run.set(
80 key,
81 DefineModelStatement {
82 if_not_exists: false,
84 ..self.clone()
85 },
86 )
87 .await?;
88 Ok(Value::None)
92 }
93}
94
95impl InfoStructure for DefineModelStatement {
96 fn structure(self) -> Value {
97 let Self {
98 name,
99 version,
100 comment,
101 permissions,
102 ..
103 } = self;
104 let mut acc = Object::default();
105
106 acc.insert("name".to_string(), name.structure());
107
108 acc.insert("version".to_string(), version.into());
109
110 if let Some(comment) = comment {
111 acc.insert("comment".to_string(), comment.into());
112 }
113
114 acc.insert("permissions".to_string(), permissions.structure());
115
116 Value::Object(acc)
117 }
118}