surrealdb_expr/expr/
table_type.rs1use common::fmt::EscapeKwFreeIdent;
8use revision::revisioned;
9use surrealdb_types::{SqlFormat, ToSql, write_sql};
10
11use crate::expr::Kind;
12use crate::expr::statements::info::InfoStructure;
13use crate::sql;
14use crate::val::{TableName, Value};
15
16#[revisioned(revision = 1)]
18#[derive(Debug, Default, Hash, Clone, Eq, PartialEq)]
19pub enum TableType {
20 #[default]
21 Any,
22 Normal,
23 Relation(Relation),
24}
25
26impl ToSql for TableType {
27 fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
28 match self {
29 TableType::Any => f.push_str("ANY"),
30 TableType::Normal => f.push_str("NORMAL"),
31 TableType::Relation(rel) => {
32 f.push_str("RELATION");
33 if !rel.from.is_empty() {
34 f.push_str(" IN ");
35 for (idx, k) in rel.from.iter().enumerate() {
36 if idx != 0 {
37 f.push_str(" | ");
38 }
39 write_sql!(f, sql_fmt, "{}", EscapeKwFreeIdent(k.as_str()));
40 }
41 }
42 if !rel.to.is_empty() {
43 f.push_str(" OUT ");
44 for (idx, k) in rel.to.iter().enumerate() {
45 if idx != 0 {
46 f.push_str(" | ");
47 }
48 write_sql!(f, sql_fmt, "{}", EscapeKwFreeIdent(k.as_str()));
49 }
50 }
51 if rel.enforced {
52 f.push_str(" ENFORCED");
53 }
54 if rel.lightweight {
55 f.push_str(" LIGHTWEIGHT");
56 }
57 }
58 }
59 }
60}
61
62impl InfoStructure for TableType {
63 fn structure(self) -> Value {
64 match self {
65 Self::Any => Value::from(map! {
66 "kind" => "ANY".into(),
67 }),
68 Self::Normal => Value::from(map! {
69 "kind" => "NORMAL".into(),
70 }),
71 Self::Relation(rel) => Value::from(map! {
72 "kind" => "RELATION".into(),
73 "in", if !rel.from.is_empty() =>
74 rel.from.into_iter().map(Value::Table).collect::<Vec<_>>().into(),
75 "out", if !rel.to.is_empty() =>
76 rel.to.into_iter().map(Value::Table).collect::<Vec<_>>().into(),
77 "enforced" => rel.enforced.into(),
78 "lightweight", if rel.lightweight => true.into()
79 }),
80 }
81 }
82}
83
84impl From<sql::table_type::TableType> for TableType {
85 fn from(v: sql::table_type::TableType) -> Self {
86 match v {
87 sql::table_type::TableType::Any => Self::Any,
88 sql::table_type::TableType::Normal => Self::Normal,
89 sql::table_type::TableType::Relation(rel) => Self::Relation(rel.into()),
90 }
91 }
92}
93
94impl From<TableType> for sql::table_type::TableType {
95 fn from(v: TableType) -> Self {
96 match v {
97 TableType::Any => Self::Any,
98 TableType::Normal => Self::Normal,
99 TableType::Relation(rel) => Self::Relation(rel.into()),
100 }
101 }
102}
103
104#[revisioned(revision = 3)]
105#[derive(Debug, Hash, Clone, Eq, PartialEq)]
106pub struct Relation {
107 #[revision(end = 2, convert_fn = "rev_convert_from")]
108 pub old_from: Option<Kind>,
109 #[revision(start = 2)]
112 pub from: Vec<TableName>,
113 #[revision(end = 2, convert_fn = "rev_convert_to")]
114 pub old_to: Option<Kind>,
115 #[revision(start = 2)]
118 pub to: Vec<TableName>,
119 pub enforced: bool,
120 #[revision(start = 3)]
127 pub lightweight: bool,
128}
129
130impl Relation {
131 fn rev_convert_from(&mut self, _rev: u16, value: Option<Kind>) -> Result<(), revision::Error> {
132 if let Some(x) = value {
133 let Kind::Record(x) = x else {
134 return Err(revision::Error::Conversion(format!(
135 "Invalid kind within table relation, should have been a record, found: {:#?}",
136 x,
137 )));
138 };
139 self.from = x
140 }
141 Ok(())
142 }
143 fn rev_convert_to(&mut self, _rev: u16, value: Option<Kind>) -> Result<(), revision::Error> {
144 if let Some(x) = value {
145 let Kind::Record(x) = x else {
146 return Err(revision::Error::Conversion(format!(
147 "Invalid kind within table relation, should have been a record, found: {:#?}",
148 x,
149 )));
150 };
151 self.to = x
152 }
153 Ok(())
154 }
155}
156
157impl From<sql::table_type::Relation> for Relation {
158 fn from(v: sql::table_type::Relation) -> Self {
159 Self {
160 from: v.from.into_iter().map(Into::into).collect(),
161 to: v.to.into_iter().map(Into::into).collect(),
162 enforced: v.enforced,
163 lightweight: v.lightweight,
164 }
165 }
166}
167
168impl From<Relation> for sql::table_type::Relation {
169 fn from(v: Relation) -> Self {
170 Self {
171 from: v.from.into_iter().map(Into::into).collect(),
172 to: v.to.into_iter().map(Into::into).collect(),
173 enforced: v.enforced,
174 lightweight: v.lightweight,
175 }
176 }
177}