surrealdb_core/sql/statements/define/
database.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::{changefeed::ChangeFeed, 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 DefineDatabaseStatement {
18 pub id: Option<u32>,
19 pub name: Ident,
20 pub comment: Option<Strand>,
21 pub changefeed: Option<ChangeFeed>,
22 #[revision(start = 2)]
23 pub if_not_exists: bool,
24 #[revision(start = 3)]
25 pub overwrite: bool,
26}
27
28impl DefineDatabaseStatement {
29 pub(crate) async fn compute(
31 &self,
32 ctx: &Context,
33 opt: &Options,
34 _doc: Option<&CursorDoc>,
35 ) -> Result<Value, Error> {
36 opt.is_allowed(Action::Edit, ResourceKind::Database, &Base::Ns)?;
38 let ns = opt.ns()?;
40 let txn = ctx.tx();
42 if txn.get_db(ns, &self.name).await.is_ok() {
44 if self.if_not_exists {
45 return Ok(Value::None);
46 } else if !self.overwrite {
47 return Err(Error::DbAlreadyExists {
48 name: self.name.to_string(),
49 });
50 }
51 }
52 let key = crate::key::namespace::db::new(ns, &self.name);
54 let nsv = txn.get_or_add_ns(ns, opt.strict).await?;
55 txn.set(
56 key,
57 revision::to_vec(&DefineDatabaseStatement {
58 id: if self.id.is_none() && nsv.id.is_some() {
59 Some(txn.lock().await.get_next_db_id(nsv.id.unwrap()).await?)
60 } else {
61 None
62 },
63 if_not_exists: false,
65 overwrite: false,
66 ..self.clone()
67 })?,
68 None,
69 )
70 .await?;
71 if let Some(cache) = ctx.get_cache() {
73 cache.clear();
74 }
75 txn.clear();
77 Ok(Value::None)
79 }
80}
81
82impl Display for DefineDatabaseStatement {
83 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84 write!(f, "DEFINE DATABASE")?;
85 if self.if_not_exists {
86 write!(f, " IF NOT EXISTS")?
87 }
88 if self.overwrite {
89 write!(f, " OVERWRITE")?
90 }
91 write!(f, " {}", self.name)?;
92 if let Some(ref v) = self.comment {
93 write!(f, " COMMENT {v}")?
94 }
95 if let Some(ref v) = self.changefeed {
96 write!(f, " {v}")?;
97 }
98 Ok(())
99 }
100}
101
102impl InfoStructure for DefineDatabaseStatement {
103 fn structure(self) -> Value {
104 Value::from(map! {
105 "name".to_string() => self.name.structure(),
106 "comment".to_string(), if let Some(v) = self.comment => v.into(),
107 })
108 }
109}