surrealdb_sql/
table_name.rs1use std::borrow::{Borrow, Cow};
2use std::fmt::{self, Display};
3
4use common::fmt::EscapeIdent;
5use surrealdb_strand::Strand;
6use surrealdb_types::{SqlFormat, ToSql};
7
8#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
24#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
25#[repr(transparent)]
26pub struct TableName(Strand);
27
28impl TableName {
29 pub fn new(s: impl Into<Strand>) -> TableName {
31 TableName(s.into())
32 }
33
34 pub fn into_string(self) -> String {
35 self.0.into()
36 }
37
38 pub fn as_str(&self) -> &str {
39 self.0.as_str()
40 }
41
42 pub fn is_table_type(&self, tables: &[TableName]) -> bool {
43 tables.is_empty() || tables.contains(self)
44 }
45}
46
47impl From<String> for TableName {
48 fn from(value: String) -> Self {
49 TableName(value.into())
50 }
51}
52
53impl From<TableName> for String {
54 fn from(value: TableName) -> Self {
55 value.0.into()
56 }
57}
58
59impl From<&str> for TableName {
60 fn from(value: &str) -> Self {
61 TableName(Strand::from(value))
62 }
63}
64
65impl From<Strand> for TableName {
66 fn from(value: Strand) -> Self {
67 TableName(value)
68 }
69}
70
71impl From<TableName> for Strand {
72 fn from(value: TableName) -> Self {
73 value.0
74 }
75}
76
77impl<'a> From<TableName> for Cow<'a, str> {
78 fn from(value: TableName) -> Self {
79 Cow::Owned(value.into_string())
80 }
81}
82
83impl From<TableName> for surrealdb_strand::TableName {
85 fn from(value: TableName) -> Self {
86 surrealdb_strand::TableName::from(value.0)
87 }
88}
89
90impl From<surrealdb_strand::TableName> for TableName {
93 fn from(value: surrealdb_strand::TableName) -> Self {
94 TableName(Strand::from(value))
95 }
96}
97
98impl From<surrealdb_types::Table> for TableName {
99 fn from(value: surrealdb_types::Table) -> Self {
100 TableName(Strand::from(value.into_string()))
101 }
102}
103
104impl From<TableName> for surrealdb_types::Table {
105 fn from(value: TableName) -> Self {
106 surrealdb_types::Table::new(value.into_string())
107 }
108}
109
110impl ToSql for TableName {
111 fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
112 EscapeIdent(self.as_str()).fmt_sql(f, sql_fmt);
113 }
114}
115
116impl PartialEq<TableName> for &TableName {
117 fn eq(&self, other: &TableName) -> bool {
118 self.0 == other.0
119 }
120}
121
122impl PartialEq<str> for TableName {
123 fn eq(&self, other: &str) -> bool {
124 self.as_str() == other
125 }
126}
127
128impl PartialEq<TableName> for str {
129 fn eq(&self, other: &TableName) -> bool {
130 self == other.as_str()
131 }
132}
133
134impl PartialEq<&str> for TableName {
135 fn eq(&self, other: &&str) -> bool {
136 self.as_str() == *other
137 }
138}
139
140impl PartialEq<String> for TableName {
141 fn eq(&self, other: &String) -> bool {
142 self.as_str() == other.as_str()
143 }
144}
145
146impl AsRef<str> for TableName {
147 fn as_ref(&self) -> &str {
148 self.as_str()
149 }
150}
151
152impl Display for TableName {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 Display::fmt(self.as_str(), f)
155 }
156}
157
158impl Borrow<str> for TableName {
159 fn borrow(&self) -> &str {
160 self.as_str()
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use surrealdb_types::ToSql;
167
168 use super::TableName;
169
170 #[test]
173 fn renders_with_keyword_escaping() {
174 assert_eq!(TableName::from("users").to_sql(), "users");
175 assert_eq!(TableName::from("select").to_sql(), "`select`");
176 assert_eq!(TableName::from("a b").to_sql(), "`a b`");
177 }
178
179 #[test]
180 fn lowering_round_trips_through_the_engine_form() {
181 let language = TableName::from("users");
182 let engine: surrealdb_strand::TableName = language.clone().into();
183 assert_eq!(TableName::from(engine), language);
184 }
185}