1use std::marker::PhantomData;
2
3use crate::{IntoSqlValue, OrderClause, SortDirection, order::OrderTarget, values::FilterValue};
4
5use super::filter::Filter;
6use super::op::FilterOp;
7
8#[derive(Debug, Clone, Copy)]
9pub struct FieldRef<M, T> {
10 pub(super) column: &'static str,
11 _marker: PhantomData<fn() -> (M, T)>,
12}
13
14impl<M, T> FieldRef<M, T> {
15 pub const fn new(column: &'static str) -> Self {
16 Self {
17 column,
18 _marker: PhantomData,
19 }
20 }
21
22 pub const fn column_name(self) -> &'static str {
26 self.column
27 }
28
29 pub fn asc(self) -> OrderClause {
30 OrderClause {
31 target: OrderTarget::Column(self.column),
32 direction: SortDirection::Asc,
33 null_order: crate::NullOrder::Last,
34 }
35 }
36
37 pub fn desc(self) -> OrderClause {
38 OrderClause {
39 target: OrderTarget::Column(self.column),
40 direction: SortDirection::Desc,
41 null_order: crate::NullOrder::Last,
42 }
43 }
44}
45
46impl<M, T> FieldRef<M, T> {
47 pub fn eq<V>(self, value: V) -> Filter
48 where
49 V: IntoSqlValue,
50 {
51 Filter::single(self.column, FilterOp::Eq, value)
52 }
53
54 pub fn ne<V>(self, value: V) -> Filter
55 where
56 V: IntoSqlValue,
57 {
58 Filter::single(self.column, FilterOp::Ne, value)
59 }
60
61 pub fn in_<I, V>(self, values: I) -> Filter
62 where
63 I: IntoIterator<Item = V>,
64 V: IntoSqlValue,
65 {
66 Filter {
67 column: self.column,
68 op: FilterOp::In,
69 value: FilterValue::Many(
70 values
71 .into_iter()
72 .map(IntoSqlValue::into_sql_value)
73 .collect(),
74 ),
75 }
76 }
77
78 pub fn lt<V>(self, value: V) -> Filter
79 where
80 V: IntoSqlValue,
81 {
82 Filter::single(self.column, FilterOp::Lt, value)
83 }
84
85 pub fn lte<V>(self, value: V) -> Filter
86 where
87 V: IntoSqlValue,
88 {
89 Filter::single(self.column, FilterOp::Lte, value)
90 }
91
92 pub fn gt<V>(self, value: V) -> Filter
93 where
94 V: IntoSqlValue,
95 {
96 Filter::single(self.column, FilterOp::Gt, value)
97 }
98
99 pub fn gte<V>(self, value: V) -> Filter
100 where
101 V: IntoSqlValue,
102 {
103 Filter::single(self.column, FilterOp::Gte, value)
104 }
105
106 pub fn eq_or_null<V>(self, value: V) -> Filter
116 where
117 V: IntoSqlValue,
118 {
119 Filter::single(self.column, FilterOp::EqOrNull, value)
120 }
121
122 pub fn match_optional<V>(self, value: Option<V>) -> Option<Filter>
135 where
136 V: IntoSqlValue,
137 {
138 value.map(|v| self.eq_or_null(v))
139 }
140}
141
142impl<M> FieldRef<M, bool> {
143 pub fn is_true(self) -> Filter {
144 self.eq(true)
145 }
146
147 pub fn is_false(self) -> Filter {
148 self.eq(false)
149 }
150}
151
152impl<M> FieldRef<M, String> {
153 pub fn contains(self, value: impl Into<String>) -> Filter {
154 Filter::string_pattern(self.column, FilterOp::Contains, "%{}%", value)
155 }
156
157 pub fn starts_with(self, value: impl Into<String>) -> Filter {
158 Filter::string_pattern(self.column, FilterOp::StartsWith, "{}%", value)
159 }
160}
161
162impl<M, T> FieldRef<M, Option<T>> {
163 pub fn is_null(self) -> Filter {
164 Filter {
165 column: self.column,
166 op: FilterOp::IsNull,
167 value: FilterValue::None,
168 }
169 }
170
171 pub fn is_not_null(self) -> Filter {
172 Filter {
173 column: self.column,
174 op: FilterOp::IsNotNull,
175 value: FilterValue::None,
176 }
177 }
178}
179
180impl<M> FieldRef<M, Option<String>> {
181 pub fn contains(self, value: impl Into<String>) -> Filter {
182 Filter::string_pattern(self.column, FilterOp::Contains, "%{}%", value)
183 }
184
185 pub fn starts_with(self, value: impl Into<String>) -> Filter {
186 Filter::string_pattern(self.column, FilterOp::StartsWith, "{}%", value)
187 }
188}