Skip to main content

hamelin_lib/func/defs/
comparison.rs

1//! Comparison operators: equality, relational, and null checking
2
3use std::any::TypeId;
4
5use crate::func::def::{FunctionDef, ParameterBindingProvider, Parameters};
6use crate::func::utils::must_be_same_type;
7use crate::operator::Operator;
8use crate::types::matcher::{AnyMatcher, ExactMatcher, IntervalMatcher, NumericMatcher};
9use crate::types::{Type, BOOLEAN, STRING, TIMESTAMP, UNKNOWN};
10
11// =============================================================================
12// Timestamp comparisons
13// =============================================================================
14
15#[derive(Default, Clone)]
16pub struct TimestampEq;
17
18impl FunctionDef for TimestampEq {
19    fn name(&self) -> &'static str {
20        Operator::Eq.str()
21    }
22
23    fn parameters(&self) -> Parameters {
24        Parameters::new()
25            .with("left", ExactMatcher::of(TIMESTAMP))
26            .with("right", ExactMatcher::of(TIMESTAMP))
27    }
28
29    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
30        Ok(BOOLEAN)
31    }
32
33    fn type_id(&self) -> TypeId {
34        TypeId::of::<Self>()
35    }
36}
37
38#[derive(Default, Clone)]
39pub struct TimestampNeq;
40
41impl FunctionDef for TimestampNeq {
42    fn name(&self) -> &'static str {
43        Operator::Neq.str()
44    }
45
46    fn parameters(&self) -> Parameters {
47        Parameters::new()
48            .with("left", ExactMatcher::of(TIMESTAMP))
49            .with("right", ExactMatcher::of(TIMESTAMP))
50    }
51
52    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
53        Ok(BOOLEAN)
54    }
55
56    fn type_id(&self) -> TypeId {
57        TypeId::of::<Self>()
58    }
59}
60
61#[derive(Default, Clone)]
62pub struct TimestampLt;
63
64impl FunctionDef for TimestampLt {
65    fn name(&self) -> &'static str {
66        Operator::Lt.str()
67    }
68
69    fn parameters(&self) -> Parameters {
70        Parameters::new()
71            .with("left", ExactMatcher::of(TIMESTAMP))
72            .with("right", ExactMatcher::of(TIMESTAMP))
73    }
74
75    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
76        Ok(BOOLEAN)
77    }
78
79    fn type_id(&self) -> TypeId {
80        TypeId::of::<Self>()
81    }
82}
83
84#[derive(Default, Clone)]
85pub struct TimestampLte;
86
87impl FunctionDef for TimestampLte {
88    fn name(&self) -> &'static str {
89        Operator::Lte.str()
90    }
91
92    fn parameters(&self) -> Parameters {
93        Parameters::new()
94            .with("left", ExactMatcher::of(TIMESTAMP))
95            .with("right", ExactMatcher::of(TIMESTAMP))
96    }
97
98    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
99        Ok(BOOLEAN)
100    }
101
102    fn type_id(&self) -> TypeId {
103        TypeId::of::<Self>()
104    }
105}
106
107#[derive(Default, Clone)]
108pub struct TimestampGt;
109
110impl FunctionDef for TimestampGt {
111    fn name(&self) -> &'static str {
112        Operator::Gt.str()
113    }
114
115    fn parameters(&self) -> Parameters {
116        Parameters::new()
117            .with("left", ExactMatcher::of(TIMESTAMP))
118            .with("right", ExactMatcher::of(TIMESTAMP))
119    }
120
121    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
122        Ok(BOOLEAN)
123    }
124
125    fn type_id(&self) -> TypeId {
126        TypeId::of::<Self>()
127    }
128}
129
130#[derive(Default, Clone)]
131pub struct TimestampGte;
132
133impl FunctionDef for TimestampGte {
134    fn name(&self) -> &'static str {
135        Operator::Gte.str()
136    }
137
138    fn parameters(&self) -> Parameters {
139        Parameters::new()
140            .with("left", ExactMatcher::of(TIMESTAMP))
141            .with("right", ExactMatcher::of(TIMESTAMP))
142    }
143
144    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
145        Ok(BOOLEAN)
146    }
147
148    fn type_id(&self) -> TypeId {
149        TypeId::of::<Self>()
150    }
151}
152
153// =============================================================================
154// Interval comparisons
155// =============================================================================
156
157#[derive(Default, Clone)]
158pub struct IntervalEq;
159
160impl FunctionDef for IntervalEq {
161    fn name(&self) -> &'static str {
162        Operator::Eq.str()
163    }
164
165    fn parameters(&self) -> Parameters {
166        Parameters::new()
167            .with("left", IntervalMatcher::default())
168            .with("right", IntervalMatcher::default())
169    }
170
171    fn return_type(&self, bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
172        // Ensure both are the same interval type
173        must_be_same_type([
174            bindings.get_by_index(0)?.typ(),
175            bindings.get_by_index(1)?.typ(),
176        ])?;
177        Ok(BOOLEAN)
178    }
179
180    fn type_id(&self) -> TypeId {
181        TypeId::of::<Self>()
182    }
183}
184
185#[derive(Default, Clone)]
186pub struct IntervalNeq;
187
188impl FunctionDef for IntervalNeq {
189    fn name(&self) -> &'static str {
190        Operator::Neq.str()
191    }
192
193    fn parameters(&self) -> Parameters {
194        Parameters::new()
195            .with("left", IntervalMatcher::default())
196            .with("right", IntervalMatcher::default())
197    }
198
199    fn return_type(&self, bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
200        must_be_same_type([
201            bindings.get_by_index(0)?.typ(),
202            bindings.get_by_index(1)?.typ(),
203        ])?;
204        Ok(BOOLEAN)
205    }
206
207    fn type_id(&self) -> TypeId {
208        TypeId::of::<Self>()
209    }
210}
211
212#[derive(Default, Clone)]
213pub struct IntervalLt;
214
215impl FunctionDef for IntervalLt {
216    fn name(&self) -> &'static str {
217        Operator::Lt.str()
218    }
219
220    fn parameters(&self) -> Parameters {
221        Parameters::new()
222            .with("left", IntervalMatcher::default())
223            .with("right", IntervalMatcher::default())
224    }
225
226    fn return_type(&self, bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
227        must_be_same_type([
228            bindings.get_by_index(0)?.typ(),
229            bindings.get_by_index(1)?.typ(),
230        ])?;
231        Ok(BOOLEAN)
232    }
233
234    fn type_id(&self) -> TypeId {
235        TypeId::of::<Self>()
236    }
237}
238
239#[derive(Default, Clone)]
240pub struct IntervalLte;
241
242impl FunctionDef for IntervalLte {
243    fn name(&self) -> &'static str {
244        Operator::Lte.str()
245    }
246
247    fn parameters(&self) -> Parameters {
248        Parameters::new()
249            .with("left", IntervalMatcher::default())
250            .with("right", IntervalMatcher::default())
251    }
252
253    fn return_type(&self, bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
254        must_be_same_type([
255            bindings.get_by_index(0)?.typ(),
256            bindings.get_by_index(1)?.typ(),
257        ])?;
258        Ok(BOOLEAN)
259    }
260
261    fn type_id(&self) -> TypeId {
262        TypeId::of::<Self>()
263    }
264}
265
266#[derive(Default, Clone)]
267pub struct IntervalGt;
268
269impl FunctionDef for IntervalGt {
270    fn name(&self) -> &'static str {
271        Operator::Gt.str()
272    }
273
274    fn parameters(&self) -> Parameters {
275        Parameters::new()
276            .with("left", IntervalMatcher::default())
277            .with("right", IntervalMatcher::default())
278    }
279
280    fn return_type(&self, bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
281        must_be_same_type([
282            bindings.get_by_index(0)?.typ(),
283            bindings.get_by_index(1)?.typ(),
284        ])?;
285        Ok(BOOLEAN)
286    }
287
288    fn type_id(&self) -> TypeId {
289        TypeId::of::<Self>()
290    }
291}
292
293#[derive(Default, Clone)]
294pub struct IntervalGte;
295
296impl FunctionDef for IntervalGte {
297    fn name(&self) -> &'static str {
298        Operator::Gte.str()
299    }
300
301    fn parameters(&self) -> Parameters {
302        Parameters::new()
303            .with("left", IntervalMatcher::default())
304            .with("right", IntervalMatcher::default())
305    }
306
307    fn return_type(&self, bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
308        must_be_same_type([
309            bindings.get_by_index(0)?.typ(),
310            bindings.get_by_index(1)?.typ(),
311        ])?;
312        Ok(BOOLEAN)
313    }
314
315    fn type_id(&self) -> TypeId {
316        TypeId::of::<Self>()
317    }
318}
319
320// =============================================================================
321// Boolean comparisons
322// =============================================================================
323
324#[derive(Default, Clone)]
325pub struct BooleanEq;
326
327impl FunctionDef for BooleanEq {
328    fn name(&self) -> &'static str {
329        Operator::Eq.str()
330    }
331
332    fn parameters(&self) -> Parameters {
333        Parameters::new()
334            .with("left", ExactMatcher::of(BOOLEAN))
335            .with("right", ExactMatcher::of(BOOLEAN))
336    }
337
338    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
339        Ok(BOOLEAN)
340    }
341
342    fn type_id(&self) -> TypeId {
343        TypeId::of::<Self>()
344    }
345}
346
347#[derive(Default, Clone)]
348pub struct BooleanNeq;
349
350impl FunctionDef for BooleanNeq {
351    fn name(&self) -> &'static str {
352        Operator::Neq.str()
353    }
354
355    fn parameters(&self) -> Parameters {
356        Parameters::new()
357            .with("left", ExactMatcher::of(BOOLEAN))
358            .with("right", ExactMatcher::of(BOOLEAN))
359    }
360
361    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
362        Ok(BOOLEAN)
363    }
364
365    fn type_id(&self) -> TypeId {
366        TypeId::of::<Self>()
367    }
368}
369
370// =============================================================================
371// String comparisons
372// =============================================================================
373
374#[derive(Default, Clone)]
375pub struct StringEq;
376
377impl FunctionDef for StringEq {
378    fn name(&self) -> &'static str {
379        Operator::Eq.str()
380    }
381
382    fn parameters(&self) -> Parameters {
383        Parameters::new()
384            .with("left", ExactMatcher::of(STRING))
385            .with("right", ExactMatcher::of(STRING))
386    }
387
388    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
389        Ok(BOOLEAN)
390    }
391
392    fn type_id(&self) -> TypeId {
393        TypeId::of::<Self>()
394    }
395}
396
397#[derive(Default, Clone)]
398pub struct StringNeq;
399
400impl FunctionDef for StringNeq {
401    fn name(&self) -> &'static str {
402        Operator::Neq.str()
403    }
404
405    fn parameters(&self) -> Parameters {
406        Parameters::new()
407            .with("left", ExactMatcher::of(STRING))
408            .with("right", ExactMatcher::of(STRING))
409    }
410
411    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
412        Ok(BOOLEAN)
413    }
414
415    fn type_id(&self) -> TypeId {
416        TypeId::of::<Self>()
417    }
418}
419
420// =============================================================================
421// Numeric comparisons
422// =============================================================================
423
424#[derive(Default, Clone)]
425pub struct NumericEq;
426
427impl FunctionDef for NumericEq {
428    fn name(&self) -> &'static str {
429        Operator::Eq.str()
430    }
431
432    fn parameters(&self) -> Parameters {
433        Parameters::new()
434            .with("left", NumericMatcher::default())
435            .with("right", NumericMatcher::default())
436    }
437
438    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
439        Ok(BOOLEAN)
440    }
441
442    fn type_id(&self) -> TypeId {
443        TypeId::of::<Self>()
444    }
445}
446
447#[derive(Default, Clone)]
448pub struct NumericNeq;
449
450impl FunctionDef for NumericNeq {
451    fn name(&self) -> &'static str {
452        Operator::Neq.str()
453    }
454
455    fn parameters(&self) -> Parameters {
456        Parameters::new()
457            .with("left", NumericMatcher::default())
458            .with("right", NumericMatcher::default())
459    }
460
461    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
462        Ok(BOOLEAN)
463    }
464
465    fn type_id(&self) -> TypeId {
466        TypeId::of::<Self>()
467    }
468}
469
470#[derive(Default, Clone)]
471pub struct NumericLt;
472
473impl FunctionDef for NumericLt {
474    fn name(&self) -> &'static str {
475        Operator::Lt.str()
476    }
477
478    fn parameters(&self) -> Parameters {
479        Parameters::new()
480            .with("left", NumericMatcher::default())
481            .with("right", NumericMatcher::default())
482    }
483
484    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
485        Ok(BOOLEAN)
486    }
487
488    fn type_id(&self) -> TypeId {
489        TypeId::of::<Self>()
490    }
491}
492
493#[derive(Default, Clone)]
494pub struct NumericLte;
495
496impl FunctionDef for NumericLte {
497    fn name(&self) -> &'static str {
498        Operator::Lte.str()
499    }
500
501    fn parameters(&self) -> Parameters {
502        Parameters::new()
503            .with("left", NumericMatcher::default())
504            .with("right", NumericMatcher::default())
505    }
506
507    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
508        Ok(BOOLEAN)
509    }
510
511    fn type_id(&self) -> TypeId {
512        TypeId::of::<Self>()
513    }
514}
515
516#[derive(Default, Clone)]
517pub struct NumericGt;
518
519impl FunctionDef for NumericGt {
520    fn name(&self) -> &'static str {
521        Operator::Gt.str()
522    }
523
524    fn parameters(&self) -> Parameters {
525        Parameters::new()
526            .with("left", NumericMatcher::default())
527            .with("right", NumericMatcher::default())
528    }
529
530    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
531        Ok(BOOLEAN)
532    }
533
534    fn type_id(&self) -> TypeId {
535        TypeId::of::<Self>()
536    }
537}
538
539#[derive(Default, Clone)]
540pub struct NumericGte;
541
542impl FunctionDef for NumericGte {
543    fn name(&self) -> &'static str {
544        Operator::Gte.str()
545    }
546
547    fn parameters(&self) -> Parameters {
548        Parameters::new()
549            .with("left", NumericMatcher::default())
550            .with("right", NumericMatcher::default())
551    }
552
553    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
554        Ok(BOOLEAN)
555    }
556
557    fn type_id(&self) -> TypeId {
558        TypeId::of::<Self>()
559    }
560}
561
562// =============================================================================
563// IS / IS NOT (null checking)
564// =============================================================================
565
566#[derive(Default, Clone)]
567pub struct Is;
568
569impl FunctionDef for Is {
570    fn name(&self) -> &'static str {
571        Operator::Is.str()
572    }
573
574    fn parameters(&self) -> Parameters {
575        Parameters::new()
576            .with("left", AnyMatcher::default())
577            .with("right", ExactMatcher::of(UNKNOWN))
578    }
579
580    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
581        Ok(BOOLEAN)
582    }
583
584    fn type_id(&self) -> TypeId {
585        TypeId::of::<Self>()
586    }
587}
588
589#[derive(Default, Clone)]
590pub struct IsNot;
591
592impl FunctionDef for IsNot {
593    fn name(&self) -> &'static str {
594        Operator::IsNot.str()
595    }
596
597    fn parameters(&self) -> Parameters {
598        Parameters::new()
599            .with("left", AnyMatcher::default())
600            .with("right", ExactMatcher::of(UNKNOWN))
601    }
602
603    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
604        Ok(BOOLEAN)
605    }
606
607    fn type_id(&self) -> TypeId {
608        TypeId::of::<Self>()
609    }
610}