Skip to main content

qraft_core/expression/
fn_call.rs

1//! Portable scalar function expressions.
2
3use crate::{
4    BigInt, Date, LowerCompatible, Numeric, Text, Time, Timestamp,
5    expression::Expression,
6    lower::{Instructions, LowerCtx},
7};
8
9/// Emits the dialect's random-number function.
10pub struct Random;
11/// Emits `current_date`.
12pub struct CurrentDate;
13/// Emits `current_time`.
14pub struct CurrentTime;
15/// Emits `current_timestamp`.
16pub struct Now;
17/// Emits a typed SQL `null`.
18pub struct Null<T>(std::marker::PhantomData<T>);
19
20/// Emits `lower(...)`.
21pub struct Lower<E> {
22    inner: E,
23}
24
25/// Emits `upper(...)`.
26pub struct Upper<E> {
27    inner: E,
28}
29
30/// Emits `length(...)`.
31pub struct Length<E> {
32    inner: E,
33}
34
35/// Emits `abs(...)`.
36pub struct Abs<E> {
37    inner: E,
38}
39
40/// Emits `round(...)`.
41pub struct Round<E> {
42    inner: E,
43}
44
45/// Emits `nullif(left, right)`.
46pub struct NullIf<L, R> {
47    left: L,
48    right: R,
49}
50
51/// Emits `coalesce(left, right)`.
52pub struct Coalesce<L, R> {
53    left: L,
54    right: R,
55}
56
57/// Builds a portable random-number expression.
58pub fn random() -> Random {
59    Random
60}
61
62/// Builds a `current_date` expression.
63pub fn current_date() -> CurrentDate {
64    CurrentDate
65}
66
67/// Builds a `current_time` expression.
68pub fn current_time() -> CurrentTime {
69    CurrentTime
70}
71
72/// Builds a `current_timestamp` expression.
73pub fn now() -> Now {
74    Now
75}
76
77/// Builds a typed `null` expression.
78pub fn null<T>() -> Null<T> {
79    Null(std::marker::PhantomData)
80}
81
82/// Builds a `lower(...)` expression.
83pub fn lower<E>(inner: E) -> Lower<E> {
84    Lower { inner }
85}
86
87/// Builds an `upper(...)` expression.
88pub fn upper<E>(inner: E) -> Upper<E> {
89    Upper { inner }
90}
91
92/// Builds a `length(...)` expression.
93pub fn length<E>(inner: E) -> Length<E> {
94    Length { inner }
95}
96
97/// Builds an `abs(...)` expression.
98pub fn abs<E>(inner: E) -> Abs<E> {
99    Abs { inner }
100}
101
102/// Builds a `round(...)` expression.
103pub fn round<E>(inner: E) -> Round<E> {
104    Round { inner }
105}
106
107/// Builds a `nullif(left, right)` expression.
108pub fn null_if<L, R>(left: L, right: R) -> NullIf<L, R> {
109    NullIf { left, right }
110}
111
112/// Builds a `coalesce(left, right)` expression.
113pub fn coalesce<L, R>(left: L, right: R) -> Coalesce<L, R> {
114    Coalesce { left, right }
115}
116
117#[qraft_expression_macro::as_expression]
118impl Expression for Random {
119    type Type = crate::Double;
120
121    fn lower(&self, ctx: &mut LowerCtx) -> usize {
122        ctx.lower_fn("random", 0)
123    }
124}
125
126#[qraft_expression_macro::as_expression]
127impl Expression for CurrentDate {
128    type Type = Date;
129
130    fn lower(&self, ctx: &mut LowerCtx) -> usize {
131        ctx.lower_fn("current_date", 0)
132    }
133}
134
135#[qraft_expression_macro::as_expression]
136impl Expression for CurrentTime {
137    type Type = Time;
138
139    fn lower(&self, ctx: &mut LowerCtx) -> usize {
140        ctx.lower_fn("current_time", 0)
141    }
142}
143
144#[qraft_expression_macro::as_expression]
145impl Expression for Now {
146    type Type = Timestamp;
147
148    fn lower(&self, ctx: &mut LowerCtx) -> usize {
149        ctx.lower_fn("current_timestamp", 0)
150    }
151}
152
153#[qraft_expression_macro::as_expression]
154impl<T> Expression for Null<T>
155where
156    T: crate::TypeMeta,
157{
158    type Type = crate::Nullable<T>;
159
160    fn lower(&self, ctx: &mut LowerCtx) -> usize {
161        ctx.lower_null()
162    }
163}
164
165#[qraft_expression_macro::as_expression]
166impl<E> Expression for Lower<E>
167where
168    E: Expression<Type = Text>,
169{
170    type Type = Text;
171
172    fn lower(&self, ctx: &mut LowerCtx) -> usize {
173        let inner = self.inner.lower(ctx);
174        ctx.lower_fn("lower", inner)
175    }
176}
177
178#[qraft_expression_macro::as_expression]
179impl<E> Expression for Upper<E>
180where
181    E: Expression<Type = Text>,
182{
183    type Type = Text;
184
185    fn lower(&self, ctx: &mut LowerCtx) -> usize {
186        let inner = self.inner.lower(ctx);
187        ctx.lower_fn("upper", inner)
188    }
189}
190
191#[qraft_expression_macro::as_expression]
192impl<E> Expression for Length<E>
193where
194    E: Expression<Type = Text>,
195{
196    type Type = BigInt;
197
198    fn lower(&self, ctx: &mut LowerCtx) -> usize {
199        let inner = self.inner.lower(ctx);
200        ctx.lower_fn("length", inner)
201    }
202}
203
204#[qraft_expression_macro::as_expression]
205impl<E> Expression for Abs<E>
206where
207    E: Expression,
208    E::Type: Numeric,
209{
210    type Type = E::Type;
211
212    fn lower(&self, ctx: &mut LowerCtx) -> usize {
213        let inner = self.inner.lower(ctx);
214        ctx.lower_fn("abs", inner)
215    }
216}
217
218#[qraft_expression_macro::as_expression]
219impl<E> Expression for Round<E>
220where
221    E: Expression,
222    E::Type: Numeric,
223{
224    type Type = E::Type;
225
226    fn lower(&self, ctx: &mut LowerCtx) -> usize {
227        let inner = self.inner.lower(ctx);
228        ctx.lower_fn("round", inner)
229    }
230}
231
232#[qraft_expression_macro::as_expression]
233impl<L, R> Expression for NullIf<L, R>
234where
235    L: Expression,
236    R: LowerCompatible<L::Type>,
237{
238    type Type = L::Type;
239
240    fn lower(&self, ctx: &mut LowerCtx) -> usize {
241        let lhs = self.left.lower(ctx);
242        let rhs = self.right.lower_compatible(ctx);
243        ctx.instrs.push_seperated(2);
244        ctx.lower_fn("nullif", lhs + rhs + 1)
245    }
246}
247
248#[qraft_expression_macro::as_expression]
249impl<L, R> Expression for Coalesce<L, R>
250where
251    L: Expression,
252    R: LowerCompatible<L::Type>,
253{
254    type Type = L::Type;
255
256    fn lower(&self, ctx: &mut LowerCtx) -> usize {
257        let lhs = self.left.lower(ctx);
258        let rhs = self.right.lower_compatible(ctx);
259        ctx.instrs.push_seperated(2);
260        ctx.lower_fn("coalesce", lhs + rhs + 1)
261    }
262}