surrealdb_sql/statements/define/
table.rs1use crate::ctx::Context;
2use crate::dbs::{Options, Transaction};
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::iam::{Action, ResourceKind};
6use crate::{
7 changefeed::ChangeFeed,
8 fmt::{is_pretty, pretty_indent},
9 statements::UpdateStatement,
10 Base, Ident, Permissions, Strand, Value, Values, View,
11};
12use derive::Store;
13use revision::revisioned;
14use serde::{Deserialize, Serialize};
15use std::fmt::{self, Display, Write};
16
17#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
18#[revisioned(revision = 1)]
19pub struct DefineTableStatement {
20 pub id: Option<u32>,
21 pub name: Ident,
22 pub drop: bool,
23 pub full: bool,
24 pub view: Option<View>,
25 pub permissions: Permissions,
26 pub changefeed: Option<ChangeFeed>,
27 pub comment: Option<Strand>,
28}
29
30impl DefineTableStatement {
31 pub(crate) async fn compute(
32 &self,
33 ctx: &Context<'_>,
34 opt: &Options,
35 txn: &Transaction,
36 doc: Option<&CursorDoc<'_>>,
37 ) -> Result<Value, Error> {
38 opt.is_allowed(Action::Edit, ResourceKind::Table, &Base::Db)?;
40 let mut run = txn.lock().await;
42 run.clear_cache();
44 let key = crate::key::database::tb::new(opt.ns(), opt.db(), &self.name);
46 let ns = run.add_ns(opt.ns(), opt.strict).await?;
47 let db = run.add_db(opt.ns(), opt.db(), opt.strict).await?;
48 let dt = if self.id.is_none() && ns.id.is_some() && db.id.is_some() {
49 let mut tb = self.clone();
50 tb.id = Some(run.get_next_tb_id(ns.id.unwrap(), db.id.unwrap()).await?);
51 run.set(key, &tb).await?;
52 tb
53 } else {
54 run.set(key, self).await?;
55 self.to_owned()
56 };
57 if let Some(view) = &self.view {
59 let key = crate::key::table::all::new(opt.ns(), opt.db(), &self.name);
61 run.delp(key, u32::MAX).await?;
62 for v in view.what.0.iter() {
64 let key = crate::key::table::ft::new(opt.ns(), opt.db(), v, &self.name);
66 run.set(key, self).await?;
67 let key = crate::key::table::ft::prefix(opt.ns(), opt.db(), v);
69 run.clr(key).await?;
70 }
71 drop(run);
73 let opt = &opt.new_with_force(true);
75 let opt = &opt.new_with_fields(false);
77 let opt = &opt.new_with_events(false);
79 let opt = &opt.new_with_indexes(false);
81 for v in view.what.0.iter() {
83 let stm = UpdateStatement {
85 what: Values(vec![Value::Table(v.clone())]),
86 ..UpdateStatement::default()
87 };
88 stm.compute(ctx, opt, txn, doc).await?;
89 }
90 } else if dt.changefeed.is_some() {
91 run.record_table_change(opt.ns(), opt.db(), self.name.0.as_str(), &dt);
92 }
93 Ok(Value::None)
95 }
96}
97
98impl Display for DefineTableStatement {
99 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100 write!(f, "DEFINE TABLE {}", self.name)?;
101 if self.drop {
102 f.write_str(" DROP")?;
103 }
104 f.write_str(if self.full {
105 " SCHEMAFULL"
106 } else {
107 " SCHEMALESS"
108 })?;
109 if let Some(ref v) = self.comment {
110 write!(f, " COMMENT {v}")?
111 }
112 if let Some(ref v) = self.view {
113 write!(f, " {v}")?
114 }
115 if let Some(ref v) = self.changefeed {
116 write!(f, " {v}")?;
117 }
118 let _indent = if is_pretty() {
119 Some(pretty_indent())
120 } else {
121 f.write_char(' ')?;
122 None
123 };
124 write!(f, "{}", self.permissions)?;
125 Ok(())
126 }
127}