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::fmt::{is_pretty, pretty_indent};
7use crate::sql::statements::info::InfoStructure;
8use crate::sql::{Base, Ident, Permission, Strand, Value};
9
10use revision::revisioned;
11use serde::{Deserialize, Serialize};
12use std::fmt::{self, Write};
13
14#[revisioned(revision = 3)]
15#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
16#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
17#[non_exhaustive]
18pub struct DefineModelStatement {
19 pub hash: String,
20 pub name: Ident,
21 pub version: String,
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 DefineModelStatement {
31 pub(crate) async fn compute(
33 &self,
34 ctx: &Context,
35 opt: &Options,
36 _doc: Option<&CursorDoc>,
37 ) -> Result<Value, Error> {
38 opt.is_allowed(Action::Edit, ResourceKind::Model, &Base::Db)?;
40 let txn = ctx.tx();
42 let (ns, db) = opt.ns_db()?;
44 if txn.get_db_model(ns, db, &self.name, &self.version).await.is_ok() {
45 if self.if_not_exists {
46 return Ok(Value::None);
47 } else if !self.overwrite {
48 return Err(Error::MlAlreadyExists {
49 name: self.name.to_string(),
50 });
51 }
52 }
53 let key = crate::key::database::ml::new(ns, db, &self.name, &self.version);
55 txn.get_or_add_ns(ns, opt.strict).await?;
56 txn.get_or_add_db(ns, db, opt.strict).await?;
57 txn.set(
58 key,
59 revision::to_vec(&DefineModelStatement {
60 if_not_exists: false,
62 overwrite: false,
63 ..self.clone()
64 })?,
65 None,
66 )
67 .await?;
68 txn.clear();
70 Ok(Value::None)
72 }
73}
74
75impl fmt::Display for DefineModelStatement {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 write!(f, "DEFINE MODEL")?;
78 if self.if_not_exists {
79 write!(f, " IF NOT EXISTS")?
80 }
81 if self.overwrite {
82 write!(f, " OVERWRITE")?
83 }
84 write!(f, " ml::{}<{}>", self.name, self.version)?;
85 if let Some(comment) = self.comment.as_ref() {
86 write!(f, " COMMENT {}", comment)?;
87 }
88 let _indent = if is_pretty() {
89 Some(pretty_indent())
90 } else {
91 f.write_char(' ')?;
92 None
93 };
94 write!(f, "PERMISSIONS {}", self.permissions)?;
95 Ok(())
96 }
97}
98
99impl InfoStructure for DefineModelStatement {
100 fn structure(self) -> Value {
101 Value::from(map! {
102 "name".to_string() => self.name.structure(),
103 "version".to_string() => self.version.into(),
104 "permissions".to_string() => self.permissions.structure(),
105 "comment".to_string(), if let Some(v) = self.comment => v.into(),
106 })
107 }
108}