spacetimedb_query_builder/
table.rs1use std::marker::PhantomData;
2
3use crate::Operand;
4
5use super::{format_expr, BoolExpr, Query, RawQuery, RHS};
6
7pub type TableNameStr = &'static str;
8
9pub trait HasCols {
10 type Cols;
11 fn cols(name: TableNameStr) -> Self::Cols;
12}
13
14pub trait HasIxCols {
15 type IxCols;
16 fn ix_cols(name: TableNameStr) -> Self::IxCols;
17}
18
19pub trait CanBeLookupTable: HasIxCols {}
23
24pub struct Table<T> {
25 pub(super) table_name: TableNameStr,
26 _marker: PhantomData<T>,
27}
28
29impl<T> Table<T> {
30 pub fn new(table_name: TableNameStr) -> Self {
31 Self {
32 table_name,
33 _marker: PhantomData,
34 }
35 }
36
37 pub(super) fn name(&self) -> TableNameStr {
38 self.table_name
39 }
40}
41
42pub struct Col<T, V> {
44 pub(super) col: ColumnRef<T>,
45 _marker: PhantomData<V>,
46}
47
48impl<T, V> Col<T, V> {
49 pub fn new(table_name: &'static str, column_name: &'static str) -> Self {
50 Self {
51 col: ColumnRef::new(table_name, column_name),
52 _marker: PhantomData,
53 }
54 }
55}
56
57impl<T, V> Copy for Col<T, V> {}
58impl<T, V> Clone for Col<T, V> {
59 fn clone(&self) -> Self {
60 *self
61 }
62}
63
64impl<T, V> Col<T, V> {
65 pub fn eq<R: RHS<T, V>>(self, rhs: R) -> BoolExpr<T> {
66 BoolExpr::Eq(self.into(), rhs.to_expr())
67 }
68 pub fn ne<R: RHS<T, V>>(self, rhs: R) -> BoolExpr<T> {
69 BoolExpr::Ne(self.into(), rhs.to_expr())
70 }
71 pub fn gt<R: RHS<T, V>>(self, rhs: R) -> BoolExpr<T> {
72 BoolExpr::Gt(self.into(), rhs.to_expr())
73 }
74 pub fn lt<R: RHS<T, V>>(self, rhs: R) -> BoolExpr<T> {
75 BoolExpr::Lt(self.into(), rhs.to_expr())
76 }
77 pub fn gte<R: RHS<T, V>>(self, rhs: R) -> BoolExpr<T> {
78 BoolExpr::Gte(self.into(), rhs.to_expr())
79 }
80 pub fn lte<R: RHS<T, V>>(self, rhs: R) -> BoolExpr<T> {
81 BoolExpr::Lte(self.into(), rhs.to_expr())
82 }
83}
84
85impl<T, V> From<Col<T, V>> for Operand<T> {
86 fn from(col: Col<T, V>) -> Self {
87 Operand::Column(col.col)
88 }
89}
90
91pub struct ColumnRef<T> {
92 table_name: &'static str,
93 column_name: &'static str,
94 _marker: PhantomData<T>,
95}
96
97impl<T> ColumnRef<T> {
98 pub(super) fn new(table_name: &'static str, column_name: &'static str) -> Self {
99 Self {
100 table_name,
101 column_name,
102 _marker: PhantomData,
103 }
104 }
105
106 pub(super) fn fmt(&self) -> String {
107 format!("\"{}\".\"{}\"", self.table_name, self.column_name)
108 }
109
110 pub(super) fn column_name(&self) -> &'static str {
111 self.column_name
112 }
113
114 pub(super) fn table_name(&self) -> &'static str {
115 self.table_name
116 }
117}
118
119impl<T> Copy for ColumnRef<T> {}
120impl<T> Clone for ColumnRef<T> {
121 fn clone(&self) -> Self {
122 *self
123 }
124}
125
126pub struct FromWhere<T> {
127 pub(super) table_name: TableNameStr,
128 pub(super) expr: BoolExpr<T>,
129}
130
131impl<T: HasCols> Query<T> for Table<T> {
132 fn into_sql(self) -> String {
133 format!(r#"SELECT * FROM "{}""#, self.table_name)
134 }
135}
136
137impl<T: HasCols> Query<T> for FromWhere<T> {
138 fn into_sql(self) -> String {
139 format!(
140 r#"SELECT * FROM "{}" WHERE {}"#,
141 self.table_name,
142 format_expr(&self.expr)
143 )
144 }
145}
146
147impl<T: HasCols> Table<T> {
148 pub fn build(self) -> RawQuery<T> {
149 RawQuery::new(format!(r#"SELECT * FROM "{}""#, self.table_name))
150 }
151
152 pub fn r#where<F>(self, f: F) -> FromWhere<T>
153 where
154 F: Fn(&T::Cols) -> BoolExpr<T>,
155 {
156 let expr = f(&T::cols(self.table_name));
157 FromWhere {
158 table_name: self.table_name,
159 expr,
160 }
161 }
162
163 pub fn filter<F>(self, f: F) -> FromWhere<T>
165 where
166 F: Fn(&T::Cols) -> BoolExpr<T>,
167 {
168 self.r#where(f)
169 }
170}
171
172impl<T: HasCols> FromWhere<T> {
173 pub fn r#where<F>(self, f: F) -> Self
174 where
175 F: Fn(&T::Cols) -> BoolExpr<T>,
176 {
177 let extra = f(&T::cols(self.table_name));
178 Self {
179 table_name: self.table_name,
180 expr: self.expr.and(extra),
181 }
182 }
183
184 pub fn filter<F>(self, f: F) -> Self
186 where
187 F: Fn(&T::Cols) -> BoolExpr<T>,
188 {
189 self.r#where(f)
190 }
191
192 pub fn build(self) -> RawQuery<T> {
193 let sql = format!(
194 r#"SELECT * FROM "{}" WHERE {}"#,
195 self.table_name,
196 format_expr(&self.expr)
197 );
198 RawQuery::new(sql)
199 }
200}