Skip to main content

tank_core/expression/
expression.rs

1use crate::{
2    writer::{Context, SqlWriter},
3    AsValue, DynQuery, ExpressionVisitor, FixedDecimal, GenericSqlWriter, Interval, OpPrecedence,
4    Operand, Value,
5};
6use rust_decimal::Decimal;
7use std::{borrow::Cow, mem, sync::Arc};
8use time::UtcDateTime;
9use uuid::Uuid;
10
11/// Renderable SQL expression.
12pub trait Expression: OpPrecedence {
13    /// Generates the SQL representation of this expression.
14    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery);
15    /// Traverses the expression with a visitor.
16    ///
17    /// Returns `true` if the visitor matched this node.
18    fn accept_visitor(
19        &self,
20        _matcher: &mut dyn ExpressionVisitor,
21        _writer: &dyn SqlWriter,
22        _context: &mut Context,
23        _out: &mut DynQuery,
24    ) -> bool {
25        false
26    }
27    /// Renders the expression as a string suitable for use as an identifier.
28    fn as_identifier(&self, context: &mut Context) -> String {
29        let mut out = DynQuery::new(String::new());
30        let writer = GenericSqlWriter::new();
31        self.write_query(&writer, context, &mut out);
32        mem::take(out.buffer())
33    }
34}
35
36impl<T: Expression> Expression for &T {
37    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
38        (*self).write_query(writer, context, out);
39    }
40    fn accept_visitor(
41        &self,
42        matcher: &mut dyn ExpressionVisitor,
43        writer: &dyn SqlWriter,
44        context: &mut Context,
45        out: &mut DynQuery,
46    ) -> bool {
47        (*self).accept_visitor(matcher, writer, context, out)
48    }
49    fn as_identifier(&self, context: &mut Context) -> String {
50        (*self).as_identifier(context)
51    }
52}
53
54impl Expression for &dyn Expression {
55    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
56        (*self).write_query(writer, context, out);
57    }
58    fn accept_visitor(
59        &self,
60        matcher: &mut dyn ExpressionVisitor,
61        writer: &dyn SqlWriter,
62        context: &mut Context,
63        out: &mut DynQuery,
64    ) -> bool {
65        (*self).accept_visitor(matcher, writer, context, out)
66    }
67    fn as_identifier(&self, context: &mut Context) -> String {
68        (*self).as_identifier(context)
69    }
70}
71
72impl Expression for () {
73    fn write_query(&self, _writer: &dyn SqlWriter, _context: &mut Context, _out: &mut DynQuery) {}
74}
75
76impl Expression for bool {
77    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
78        writer.write_bool(context, out, *self);
79    }
80    fn accept_visitor(
81        &self,
82        matcher: &mut dyn ExpressionVisitor,
83        writer: &dyn SqlWriter,
84        context: &mut Context,
85        out: &mut DynQuery,
86    ) -> bool {
87        matcher.visit_operand(writer, context, out, &Operand::LitBool(*self))
88    }
89}
90
91impl Expression for &'static str {
92    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
93        writer.write_string(context, out, self);
94    }
95    fn accept_visitor(
96        &self,
97        matcher: &mut dyn ExpressionVisitor,
98        writer: &dyn SqlWriter,
99        context: &mut Context,
100        out: &mut DynQuery,
101    ) -> bool {
102        matcher.visit_operand(writer, context, out, &Operand::LitStr(*self))
103    }
104}
105
106impl Expression for Value {
107    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
108        writer.write_value(context, out, self);
109    }
110    fn accept_visitor(
111        &self,
112        matcher: &mut dyn ExpressionVisitor,
113        writer: &dyn SqlWriter,
114        context: &mut Context,
115        out: &mut DynQuery,
116    ) -> bool {
117        matcher.visit_operand(writer, context, out, &Operand::Value(self))
118    }
119}
120
121impl<'a, T: Expression> From<&'a T> for &'a dyn Expression {
122    fn from(value: &'a T) -> Self {
123        value as &'a dyn Expression
124    }
125}
126
127macro_rules! impl_expression {
128    ($($T:ty),* $(,)?) => {$(
129        impl OpPrecedence for $T {
130            fn precedence(&self, _: &dyn SqlWriter) -> i32 { 0 }
131        }
132        impl Expression for $T {
133            fn write_query(
134                &self,
135                writer: &dyn SqlWriter,
136                context: &mut Context,
137                out: &mut DynQuery,
138            ) {
139                writer.write_value(context, out, &(*self).as_value());
140            }
141        }
142    )*};
143}
144
145impl_expression!(
146    i8,
147    i16,
148    i32,
149    i64,
150    i128,
151    isize,
152    u8,
153    u16,
154    u32,
155    u64,
156    u128,
157    usize,
158    f32,
159    f64,
160    char,
161    Uuid,
162    Decimal,
163    Interval,
164    std::time::Duration,
165    time::Duration,
166    time::Date,
167    time::Time,
168    time::PrimitiveDateTime,
169    time::OffsetDateTime,
170);
171
172#[cfg(feature = "chrono")]
173impl_expression!(
174    chrono::NaiveDate,
175    chrono::NaiveTime,
176    chrono::NaiveDateTime,
177    chrono::DateTime<chrono::FixedOffset>,
178);
179
180impl OpPrecedence for UtcDateTime {
181    fn precedence(&self, _: &dyn SqlWriter) -> i32 {
182        0
183    }
184}
185impl Expression for UtcDateTime {
186    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
187        writer.write_value(
188            context,
189            out,
190            &Value::Timestamp(Some(time::PrimitiveDateTime::new(self.date(), self.time()))),
191        );
192    }
193}
194
195impl OpPrecedence for String {
196    fn precedence(&self, _: &dyn SqlWriter) -> i32 {
197        0
198    }
199}
200impl Expression for String {
201    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
202        writer.write_string(context, out, self);
203    }
204}
205
206impl OpPrecedence for Cow<'static, str> {
207    fn precedence(&self, _: &dyn SqlWriter) -> i32 {
208        0
209    }
210}
211impl Expression for Cow<'static, str> {
212    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
213        writer.write_string(context, out, self.as_ref());
214    }
215}
216
217impl OpPrecedence for Box<[u8]> {
218    fn precedence(&self, _: &dyn SqlWriter) -> i32 {
219        0
220    }
221}
222impl Expression for Box<[u8]> {
223    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
224        writer.write_value(context, out, &Value::Blob(Some(self.clone())));
225    }
226}
227
228impl OpPrecedence for serde_json::Value {
229    fn precedence(&self, _: &dyn SqlWriter) -> i32 {
230        0
231    }
232}
233impl Expression for serde_json::Value {
234    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
235        writer.write_value(context, out, &Value::Json(Some(self.clone())));
236    }
237}
238
239impl<const W: u8, const S: u8> OpPrecedence for FixedDecimal<W, S> {
240    fn precedence(&self, _: &dyn SqlWriter) -> i32 {
241        0
242    }
243}
244impl<const W: u8, const S: u8> Expression for FixedDecimal<W, S> {
245    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
246        writer.write_value(context, out, &(*self).as_value());
247    }
248}
249
250impl<T: Expression> OpPrecedence for Arc<T> {
251    fn precedence(&self, _: &dyn SqlWriter) -> i32 {
252        0
253    }
254}
255impl<T: Expression> Expression for Arc<T> {
256    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
257        (**self).write_query(writer, context, out);
258    }
259    fn accept_visitor(
260        &self,
261        matcher: &mut dyn ExpressionVisitor,
262        writer: &dyn SqlWriter,
263        context: &mut Context,
264        out: &mut DynQuery,
265    ) -> bool {
266        (**self).accept_visitor(matcher, writer, context, out)
267    }
268}
269
270impl<T: Expression> OpPrecedence for Box<T> {
271    fn precedence(&self, _: &dyn SqlWriter) -> i32 {
272        0
273    }
274}
275impl<T: Expression> Expression for Box<T> {
276    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
277        (**self).write_query(writer, context, out);
278    }
279    fn accept_visitor(
280        &self,
281        matcher: &mut dyn ExpressionVisitor,
282        writer: &dyn SqlWriter,
283        context: &mut Context,
284        out: &mut DynQuery,
285    ) -> bool {
286        (**self).accept_visitor(matcher, writer, context, out)
287    }
288}
289
290impl<T: AsValue + Expression> OpPrecedence for Option<T> {
291    fn precedence(&self, _: &dyn SqlWriter) -> i32 {
292        0
293    }
294}
295impl<T: AsValue + Expression> Expression for Option<T> {
296    fn write_query(&self, writer: &dyn SqlWriter, context: &mut Context, out: &mut DynQuery) {
297        match self {
298            Some(v) => v.write_query(writer, context, out),
299            None => writer.write_value(context, out, &T::as_empty_value()),
300        }
301    }
302}