linkrs_query/executor/expression/functions/builtin/
macros.rs1#[macro_export]
9macro_rules! define_function_enum {
10 (
11 $(#[$meta:meta])*
12 $vis:vis enum $name:ident {
13 $(
14 $(#[$variant_meta:meta])*
15 $variant:ident => {
16 name: $func_name:literal,
17 arity: $arity:expr,
18 variadic: $variadic:expr,
19 description: $desc:literal,
20 handler: $handler:expr
21 }
22 ),* $(,)?
23 }
24 ) => {
25 $(#[$meta])*
26 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
27 $vis enum $name {
28 $(
29 $(#[$variant_meta])*
30 $variant,
31 )*
32 }
33
34 impl $name {
35 $vis fn name(&self) -> &str {
37 match self {
38 $(Self::$variant => $func_name,)*
39 }
40 }
41
42 $vis fn arity(&self) -> usize {
44 match self {
45 $(Self::$variant => $arity,)*
46 }
47 }
48
49 $vis fn is_variadic(&self) -> bool {
51 match self {
52 $(Self::$variant => $variadic,)*
53 }
54 }
55
56 $vis fn description(&self) -> &str {
58 match self {
59 $(Self::$variant => $desc,)*
60 }
61 }
62
63 $vis fn execute(&self, args: &[linkrs_core::Value]) -> Result<linkrs_core::Value, $crate::executor::expression::ExpressionError> {
65 if !self.is_variadic() && args.len() != self.arity() {
66 return Err($crate::executor::expression::ExpressionError::invalid_arity(
67 self.name(),
68 self.arity(),
69 args.len(),
70 ));
71 }
72 let handler: fn(&[linkrs_core::Value]) -> Result<linkrs_core::Value, $crate::executor::expression::ExpressionError> = match self {
73 $(Self::$variant => $handler,)*
74 };
75 handler(args)
76 }
77 }
78 };
79}
80
81#[macro_export]
83macro_rules! define_unary_float_fn {
84 ($name:ident, $op:expr, $desc:literal) => {
85 fn $name(
86 args: &[linkrs_core::Value],
87 ) -> Result<linkrs_core::Value, $crate::executor::expression::ExpressionError> {
88 let op = $op;
89 match &args[0] {
90 Value::SmallInt(i) => Ok(Value::Float(op(*i as f32))),
91 Value::Int(i) => Ok(Value::Float(op(*i as f32))),
92 Value::BigInt(i) => Ok(Value::Double(op(*i as f32) as f64)),
93 Value::Float(f) => Ok(Value::Float(op(*f))),
94 Value::Double(f) => Ok(Value::Double(op(*f as f32) as f64)),
95 Value::Null(_) => Ok(Value::Null(NullType::Null)),
96 _ => Err($crate::executor::expression::ExpressionError::type_error(
97 concat!($desc, "Functions require numeric types"),
98 )),
99 }
100 }
101 };
102}
103
104#[macro_export]
106macro_rules! define_unary_numeric_fn {
107 ($name:ident, int: $int_op:expr, float: $float_op:expr, $desc:literal) => {
108 fn $name(
109 args: &[linkrs_core::Value],
110 ) -> Result<linkrs_core::Value, $crate::executor::expression::ExpressionError> {
111 match &args[0] {
112 Value::SmallInt(i) => $int_op(*i as i32),
113 Value::Int(i) => $int_op(*i),
114 Value::BigInt(i) => $int_op(*i as i32),
115 Value::Float(f) => $float_op(*f),
116 Value::Double(f) => $float_op(*f as f32),
117 Value::Null(_) => Ok(Value::Null(NullType::Null)),
118 _ => Err($crate::executor::expression::ExpressionError::type_error(
119 concat!($desc, "Functions require numeric types"),
120 )),
121 }
122 }
123 };
124}
125
126#[macro_export]
128macro_rules! define_unary_string_fn {
129 ($name:ident, $op:expr, $desc:literal) => {
130 fn $name(
131 args: &[linkrs_core::Value],
132 ) -> Result<linkrs_core::Value, $crate::executor::expression::ExpressionError> {
133 let op = $op;
134 match &args[0] {
135 Value::String(s) => Ok(Value::string(op(s))),
136 Value::Null(_) => Ok(Value::Null(NullType::Null)),
137 _ => Err($crate::executor::expression::ExpressionError::type_error(
138 concat!($desc, "Functions require a string type"),
139 )),
140 }
141 }
142 };
143}
144
145#[macro_export]
147macro_rules! define_datetime_extractor {
148 ($name:ident, Date => $date_field:ident, DateTime => $datetime_field:ident) => {
149 fn $name(
150 args: &[linkrs_core::Value],
151 ) -> Result<linkrs_core::Value, $crate::executor::expression::ExpressionError> {
152 match &args[0] {
153 Value::Date(d) => Ok(Value::BigInt(d.$date_field as i64)),
154 Value::DateTime(dt) => Ok(Value::BigInt(dt.$datetime_field as i64)),
155 Value::Null(_) => Ok(Value::Null(NullType::Null)),
156 _ => Err($crate::executor::expression::ExpressionError::type_error(
157 concat!(
158 stringify!($name),
159 "Functions require a date or datetime type"
160 ),
161 )),
162 }
163 }
164 };
165 ($name:ident, Time => $time_field:ident, DateTime => $datetime_field:ident) => {
166 fn $name(
167 args: &[linkrs_core::Value],
168 ) -> Result<linkrs_core::Value, $crate::executor::expression::ExpressionError> {
169 match &args[0] {
170 Value::Time(t) => Ok(Value::BigInt(t.$time_field as i64)),
171 Value::DateTime(dt) => Ok(Value::BigInt(dt.$datetime_field as i64)),
172 Value::Null(_) => Ok(Value::Null(NullType::Null)),
173 _ => Err($crate::executor::expression::ExpressionError::type_error(
174 concat!(
175 stringify!($name),
176 "Functions require a time or datetime type"
177 ),
178 )),
179 }
180 }
181 };
182}
183
184#[macro_export]
186macro_rules! define_binary_numeric_fn {
187 ($name:ident, $op:expr, $desc:literal) => {
188 fn $name(
189 args: &[linkrs_core::Value],
190 ) -> Result<linkrs_core::Value, $crate::executor::expression::ExpressionError> {
191 let op = $op;
192 match (&args[0], &args[1]) {
193 (Value::SmallInt(a), Value::SmallInt(b)) => op(*a as f32, *b as f32),
194 (Value::Int(a), Value::Int(b)) => op(*a as f32, *b as f32),
195 (Value::BigInt(a), Value::BigInt(b)) => op(*a as f32, *b as f32),
196 (Value::SmallInt(a), Value::Int(b)) => op(*a as f32, *b as f32),
197 (Value::Int(a), Value::SmallInt(b)) => op(*a as f32, *b as f32),
198 (Value::Float(a), Value::Float(b)) => op(*a, *b),
199 (Value::Double(a), Value::Double(b)) => op(*a as f32, *b as f32),
200 (Value::Float(a), Value::Double(b)) => op(*a, *b as f32),
201 (Value::Double(a), Value::Float(b)) => op(*a as f32, *b),
202 (Value::Null(_), _) | (_, Value::Null(_)) => Ok(Value::Null(NullType::Null)),
203 _ => Err($crate::executor::expression::ExpressionError::type_error(
204 concat!($desc, "Functions require numeric types"),
205 )),
206 }
207 }
208 };
209}
210
211#[macro_export]
213macro_rules! define_binary_string_bool_fn {
214 ($name:ident, $op:expr, $desc:literal) => {
215 fn $name(
216 args: &[linkrs_core::Value],
217 ) -> Result<linkrs_core::Value, $crate::executor::expression::ExpressionError> {
218 let op = $op;
219 match (&args[0], &args[1]) {
220 (Value::String(a), Value::String(b)) => Ok(Value::Bool(op(a, b))),
221 (Value::Null(_), _) | (_, Value::Null(_)) => Ok(Value::Null(NullType::Null)),
222 _ => Err($crate::executor::expression::ExpressionError::type_error(
223 concat!($desc, "Functions require a string type"),
224 )),
225 }
226 }
227 };
228}
229
230#[macro_export]
232macro_rules! define_binary_geography_fn {
233 ($name:ident, $op:expr, $desc:literal) => {
234 fn $name(
235 args: &[linkrs_core::Value],
236 ) -> Result<linkrs_core::Value, $crate::executor::expression::ExpressionError> {
237 let op = $op;
238 match (&args[0], &args[1]) {
239 (Value::Geography(geo1), Value::Geography(geo2)) => op(geo1, geo2),
240 (Value::Null(_), _) | (_, Value::Null(_)) => Ok(Value::Null(NullType::Null)),
241 _ => Err($crate::executor::expression::ExpressionError::type_error(
242 concat!($desc, "Functions require geo-typed parameters"),
243 )),
244 }
245 }
246 };
247}