mz_expr_derive_impl/
lib.rs
1mod sqlfunc;
17
18pub use sqlfunc::sqlfunc;
19
20#[cfg(any(feature = "test", test))]
22fn sqlfunc_for_test(
23 attr: proc_macro2::TokenStream,
24 item: proc_macro2::TokenStream,
25) -> darling::Result<proc_macro2::TokenStream> {
26 sqlfunc(attr, item, false)
27}
28
29#[cfg(any(feature = "test", test))]
30pub fn test_sqlfunc(
31 attr: proc_macro2::TokenStream,
32 item: proc_macro2::TokenStream,
33) -> (String, String) {
34 fn rust_fmt(input: &str) -> String {
35 let file = syn::parse_file(input).unwrap();
36 prettyplease::unparse(&file)
37 }
38
39 let input = rust_fmt(&format!("#[sqlfunc({attr})]\n{item}"));
40 let output = rust_fmt(
41 &sqlfunc_for_test(attr, item)
42 .unwrap_or_else(|err| err.write_errors())
43 .to_string(),
44 );
45 (output, input)
46}
47
48#[cfg(any(feature = "test", test))]
49pub fn test_sqlfunc_str(attr: &str, item: &str) -> (String, String) {
50 test_sqlfunc(attr.parse().unwrap(), item.parse().unwrap())
51}
52
53#[cfg(test)]
54mod test {
55 use quote::quote;
56
57 #[cfg_attr(miri, ignore)] #[mz_ore::test]
59 fn insta_test_add_int16() {
60 let attr = quote! {
61 is_monotone = (true, true),
62 output_type = i16,
63 is_infix_op = true,
64 sqlname = "+",
65 propagates_nulls = true
66 };
67 let item = quote! {
68 fn add_int16<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
69 a.unwrap_int16()
70 .checked_add(b.unwrap_int16())
71 .ok_or(EvalError::NumericFieldOverflow)
72 .map(Datum::from)
73 }
74 };
75 let (output, input) = super::test_sqlfunc(attr, item);
76 insta::assert_snapshot!("add_int16", output, &input);
77 }
78
79 #[cfg_attr(miri, ignore)] #[mz_ore::test]
81 fn insta_test_unary() {
82 let attr = quote! {};
83 let item = quote! {
84 fn unary_fn<'a>(a: Datum<'a>) -> bool {
85 unimplemented!()
86 }
87 };
88 let (output, input) = super::test_sqlfunc(attr, item);
89 insta::assert_snapshot!("unary_fn", output, &input);
90 }
91
92 #[cfg_attr(miri, ignore)] #[mz_ore::test]
94 fn insta_test_unary_arena() {
95 let attr = quote! {};
96 let item = quote! {
97 fn unary_fn<'a>(a: Datum<'a>, temp_storage: &RowArena) -> bool {
98 unimplemented!()
99 }
100 };
101 let (output, input) = super::test_sqlfunc(attr, item);
102 insta::assert_snapshot!("unary_arena_fn", output, &input);
103 }
104
105 #[cfg_attr(miri, ignore)] #[mz_ore::test]
107 fn insta_test_unary_ref() {
108 let attr = quote! {};
109 let item = quote! {
110 fn unary_fn<'a>(a: &i16) -> bool {
111 unimplemented!()
112 }
113 };
114 let (output, input) = super::test_sqlfunc(attr, item);
115 insta::assert_snapshot!("unary_ref", output, &input);
116 }
117
118 #[cfg_attr(miri, ignore)] #[mz_ore::test]
120 fn insta_test_complex_output_type() {
121 let attr = quote! {
122 is_monotone = (true, true),
123 output_type = "Option<bool>",
124 is_infix_op = true,
125 sqlname = "test",
126 propagates_nulls = true
127 };
128 let item = quote! {
129 fn complex_output_type_fn<'a>(a: Datum<'a>, b: Datum<'a>) -> Result<Datum<'a>, EvalError> {
130 unimplemented!()
131 }
132 };
133 let (output, input) = super::test_sqlfunc(attr, item);
134 insta::assert_snapshot!("complex_type", output, &input);
135 }
136
137 #[cfg_attr(miri, ignore)] #[mz_ore::test]
139 fn insta_test_binary_arena() {
140 let attr = quote! {};
141 let item = quote! {
142 fn unary_fn<'a>(a: Datum<'a>, b: u16, temp_storage: &RowArena) -> bool {
143 unimplemented!()
144 }
145 };
146 let (output, input) = super::test_sqlfunc(attr, item);
147 insta::assert_snapshot!("binary_arena_fn", output, &input);
148 }
149}