Skip to main content

surrealdb_sql/statements/alter/
table.rs

1use common::fmt::{EscapeKwFreeIdent, QuoteStr};
2use surrealdb_types::{SqlFormat, ToSql, write_sql};
3
4use super::AlterKind;
5use crate::{ChangeFeed, CoverStmts, Expr, Literal, Permissions, TableType};
6
7#[derive(Clone, Debug, Eq, PartialEq)]
8#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
9/// AST node for `ALTER TABLE`.
10///
11/// Supported operations include (order-insensitive after the table name):
12/// - `TYPE NORMAL | RELATION [IN <from> [OUT <to>]] | ANY`
13/// - `SCHEMAFULL` / `SCHEMALESS`
14/// - `PERMISSIONS ...`
15/// - `CHANGEFEED ...` / `DROP CHANGEFEED`
16/// - `COMMENT <string>` / `DROP COMMENT`
17/// - `COMPACT` (request table keyspace compaction)
18///
19/// Note: `COMPACT` is parsed and preserved on the expression side, however it is
20/// currently not rendered by this node's `ToSql` implementation.
21pub struct AlterTableStatement {
22	pub name: Expr,
23	pub if_exists: bool,
24	pub schemafull: AlterKind<()>,
25	pub permissions: Option<Permissions>,
26	pub changefeed: AlterKind<ChangeFeed>,
27	pub comment: AlterKind<String>,
28	pub kind: Option<TableType>,
29	/// Request table‑level compaction when true.
30	pub compact: bool,
31	/// `INLINE EDGES <n>` / `DROP INLINE EDGES`.
32	pub inline_edges_cap: AlterKind<u32>,
33	/// `INLINE REFERENCES <n>` / `DROP INLINE REFERENCES`.
34	pub inline_refs_cap: AlterKind<u32>,
35}
36
37impl Default for AlterTableStatement {
38	fn default() -> Self {
39		Self {
40			name: Expr::Literal(Literal::None),
41			if_exists: false,
42			schemafull: AlterKind::None,
43			permissions: None,
44			changefeed: AlterKind::None,
45			comment: AlterKind::None,
46			kind: None,
47			compact: false,
48			inline_edges_cap: AlterKind::None,
49			inline_refs_cap: AlterKind::None,
50		}
51	}
52}
53
54impl ToSql for AlterTableStatement {
55	fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
56		write_sql!(f, fmt, "ALTER TABLE");
57		if self.if_exists {
58			write_sql!(f, fmt, " IF EXISTS");
59		}
60		write_sql!(f, fmt, " {}", CoverStmts(&self.name));
61		if let Some(kind) = &self.kind {
62			write_sql!(f, fmt, " TYPE");
63			match &kind {
64				TableType::Normal => {
65					write_sql!(f, fmt, " NORMAL");
66				}
67				TableType::Relation(rel) => {
68					write_sql!(f, fmt, " RELATION");
69					if !rel.from.is_empty() {
70						f.push_str(" IN ");
71						for (idx, k) in rel.from.iter().enumerate() {
72							if idx != 0 {
73								f.push_str(" | ");
74							}
75							write_sql!(f, fmt, "{}", EscapeKwFreeIdent(k.as_str()));
76						}
77					}
78					if !rel.to.is_empty() {
79						f.push_str(" OUT ");
80						for (idx, k) in rel.to.iter().enumerate() {
81							if idx != 0 {
82								f.push_str(" | ");
83							}
84							write_sql!(f, fmt, "{}", EscapeKwFreeIdent(k.as_str()));
85						}
86					}
87				}
88				TableType::Any => {
89					write_sql!(f, fmt, " ANY");
90				}
91			}
92		}
93
94		match self.schemafull {
95			AlterKind::Set(_) => write_sql!(f, fmt, " SCHEMAFULL"),
96			AlterKind::Drop => write_sql!(f, fmt, " SCHEMALESS"),
97			AlterKind::None => {}
98		}
99
100		match self.comment {
101			AlterKind::Set(ref comment) => write_sql!(f, fmt, " COMMENT {}", QuoteStr(comment)),
102			AlterKind::Drop => f.push_str(" DROP COMMENT"),
103			AlterKind::None => {}
104		}
105
106		match self.changefeed {
107			AlterKind::Set(ref changefeed) => write_sql!(f, fmt, " {}", changefeed),
108			AlterKind::Drop => f.push_str(" DROP CHANGEFEED"),
109			AlterKind::None => {}
110		}
111		match self.inline_edges_cap {
112			AlterKind::Set(cap) => write_sql!(f, fmt, " INLINE EDGES {}", cap),
113			AlterKind::Drop => f.push_str(" DROP INLINE EDGES"),
114			AlterKind::None => {}
115		}
116
117		match self.inline_refs_cap {
118			AlterKind::Set(cap) => write_sql!(f, fmt, " INLINE REFERENCES {}", cap),
119			AlterKind::Drop => f.push_str(" DROP INLINE REFERENCES"),
120			AlterKind::None => {}
121		}
122
123		if let Some(permissions) = &self.permissions {
124			write_sql!(f, fmt, " {permissions}");
125		}
126
127		if self.compact {
128			write_sql!(f, fmt, " COMPACT");
129		}
130	}
131}