1use reifydb_core::{
5 expression::{
6 AddExpression, AliasExpression, AndExpression, BetweenExpression, CallExpression, CastExpression,
7 ColumnExpression, ContainsExpression, DivExpression, ElseIfExpression, EqExpression, Expression,
8 ExtendExpression, FieldAccessExpression, GreaterThanEqExpression, GreaterThanExpression, IfExpression,
9 InExpression, LessThanEqExpression, LessThanExpression, ListExpression, MapExpression, MulExpression,
10 NotEqExpression, OrExpression, PrefixExpression, RecordExpression, RemExpression, SubExpression,
11 TupleExpression, XorExpression,
12 },
13 interface::identifier::{ColumnIdentifier, ColumnObject},
14};
15use reifydb_value::fragment::Fragment;
16
17use crate::stack::{Callable, SymbolTable};
18
19pub struct ExtractedUdf {
20 pub callable: Callable,
21 pub arg_expressions: Vec<Expression>,
22 pub result_column: Fragment,
23 pub name: String,
24 pub fragment: Fragment,
25}
26
27pub fn extract_udf_calls(
28 expr: &Expression,
29 symbols: &SymbolTable,
30 counter: &mut usize,
31) -> (Expression, Vec<ExtractedUdf>) {
32 let mut extracted = Vec::new();
33 let rewritten = rewrite_expr(expr, symbols, counter, &mut extracted);
34 (rewritten, extracted)
35}
36
37fn rw(e: &Expression, s: &SymbolTable, c: &mut usize, x: &mut Vec<ExtractedUdf>) -> Expression {
38 rewrite_expr(e, s, c, x)
39}
40
41fn rw_vec(exprs: &[Expression], s: &SymbolTable, c: &mut usize, x: &mut Vec<ExtractedUdf>) -> Vec<Expression> {
42 exprs.iter().map(|e| rewrite_expr(e, s, c, x)).collect()
43}
44
45fn rewrite_expr(
46 expr: &Expression,
47 symbols: &SymbolTable,
48 counter: &mut usize,
49 extracted: &mut Vec<ExtractedUdf>,
50) -> Expression {
51 match expr {
52 Expression::Call(call) => {
53 let rewritten_args = rw_vec(&call.args, symbols, counter, extracted);
54 let function_name = call.func.0.text();
55
56 if let Some(callable) = symbols.resolve_callable(function_name) {
57 let col_name = Fragment::internal(format!("__udf_{}", counter));
58 *counter += 1;
59
60 extracted.push(ExtractedUdf {
61 callable,
62 arg_expressions: rewritten_args,
63 result_column: col_name.clone(),
64 name: function_name.to_string(),
65 fragment: call.func.0.clone(),
66 });
67
68 Expression::Column(ColumnExpression(ColumnIdentifier {
69 object: ColumnObject::Alias(Fragment::internal("")),
70 name: col_name,
71 }))
72 } else {
73 Expression::Call(CallExpression {
74 func: call.func.clone(),
75 args: rewritten_args,
76 fragment: call.fragment.clone(),
77 })
78 }
79 }
80
81 Expression::Add(e) => Expression::Add(AddExpression {
82 left: Box::new(rw(&e.left, symbols, counter, extracted)),
83 right: Box::new(rw(&e.right, symbols, counter, extracted)),
84 fragment: e.fragment.clone(),
85 }),
86 Expression::Sub(e) => Expression::Sub(SubExpression {
87 left: Box::new(rw(&e.left, symbols, counter, extracted)),
88 right: Box::new(rw(&e.right, symbols, counter, extracted)),
89 fragment: e.fragment.clone(),
90 }),
91 Expression::Mul(e) => Expression::Mul(MulExpression {
92 left: Box::new(rw(&e.left, symbols, counter, extracted)),
93 right: Box::new(rw(&e.right, symbols, counter, extracted)),
94 fragment: e.fragment.clone(),
95 }),
96 Expression::Div(e) => Expression::Div(DivExpression {
97 left: Box::new(rw(&e.left, symbols, counter, extracted)),
98 right: Box::new(rw(&e.right, symbols, counter, extracted)),
99 fragment: e.fragment.clone(),
100 }),
101 Expression::Rem(e) => Expression::Rem(RemExpression {
102 left: Box::new(rw(&e.left, symbols, counter, extracted)),
103 right: Box::new(rw(&e.right, symbols, counter, extracted)),
104 fragment: e.fragment.clone(),
105 }),
106 Expression::GreaterThan(e) => Expression::GreaterThan(GreaterThanExpression {
107 left: Box::new(rw(&e.left, symbols, counter, extracted)),
108 right: Box::new(rw(&e.right, symbols, counter, extracted)),
109 fragment: e.fragment.clone(),
110 }),
111 Expression::GreaterThanEqual(e) => Expression::GreaterThanEqual(GreaterThanEqExpression {
112 left: Box::new(rw(&e.left, symbols, counter, extracted)),
113 right: Box::new(rw(&e.right, symbols, counter, extracted)),
114 fragment: e.fragment.clone(),
115 }),
116 Expression::LessThan(e) => Expression::LessThan(LessThanExpression {
117 left: Box::new(rw(&e.left, symbols, counter, extracted)),
118 right: Box::new(rw(&e.right, symbols, counter, extracted)),
119 fragment: e.fragment.clone(),
120 }),
121 Expression::LessThanEqual(e) => Expression::LessThanEqual(LessThanEqExpression {
122 left: Box::new(rw(&e.left, symbols, counter, extracted)),
123 right: Box::new(rw(&e.right, symbols, counter, extracted)),
124 fragment: e.fragment.clone(),
125 }),
126 Expression::Equal(e) => Expression::Equal(EqExpression {
127 left: Box::new(rw(&e.left, symbols, counter, extracted)),
128 right: Box::new(rw(&e.right, symbols, counter, extracted)),
129 fragment: e.fragment.clone(),
130 }),
131 Expression::NotEqual(e) => Expression::NotEqual(NotEqExpression {
132 left: Box::new(rw(&e.left, symbols, counter, extracted)),
133 right: Box::new(rw(&e.right, symbols, counter, extracted)),
134 fragment: e.fragment.clone(),
135 }),
136 Expression::And(e) => Expression::And(AndExpression {
137 left: Box::new(rw(&e.left, symbols, counter, extracted)),
138 right: Box::new(rw(&e.right, symbols, counter, extracted)),
139 fragment: e.fragment.clone(),
140 }),
141 Expression::Or(e) => Expression::Or(OrExpression {
142 left: Box::new(rw(&e.left, symbols, counter, extracted)),
143 right: Box::new(rw(&e.right, symbols, counter, extracted)),
144 fragment: e.fragment.clone(),
145 }),
146 Expression::Xor(e) => Expression::Xor(XorExpression {
147 left: Box::new(rw(&e.left, symbols, counter, extracted)),
148 right: Box::new(rw(&e.right, symbols, counter, extracted)),
149 fragment: e.fragment.clone(),
150 }),
151
152 Expression::Between(e) => Expression::Between(BetweenExpression {
153 value: Box::new(rw(&e.value, symbols, counter, extracted)),
154 lower: Box::new(rw(&e.lower, symbols, counter, extracted)),
155 upper: Box::new(rw(&e.upper, symbols, counter, extracted)),
156 fragment: e.fragment.clone(),
157 }),
158 Expression::In(e) => Expression::In(InExpression {
159 value: Box::new(rw(&e.value, symbols, counter, extracted)),
160 list: Box::new(rw(&e.list, symbols, counter, extracted)),
161 negated: e.negated,
162 fragment: e.fragment.clone(),
163 }),
164 Expression::Contains(e) => Expression::Contains(ContainsExpression {
165 value: Box::new(rw(&e.value, symbols, counter, extracted)),
166 list: Box::new(rw(&e.list, symbols, counter, extracted)),
167 fragment: e.fragment.clone(),
168 }),
169 Expression::Cast(e) => Expression::Cast(CastExpression {
170 expression: Box::new(rw(&e.expression, symbols, counter, extracted)),
171 to: e.to.clone(),
172 fragment: e.fragment.clone(),
173 }),
174 Expression::Prefix(e) => Expression::Prefix(PrefixExpression {
175 operator: e.operator.clone(),
176 expression: Box::new(rw(&e.expression, symbols, counter, extracted)),
177 fragment: e.fragment.clone(),
178 }),
179 Expression::Alias(e) => Expression::Alias(AliasExpression {
180 alias: e.alias.clone(),
181 expression: Box::new(rw(&e.expression, symbols, counter, extracted)),
182 fragment: e.fragment.clone(),
183 }),
184 Expression::If(e) => Expression::If(IfExpression {
185 condition: Box::new(rw(&e.condition, symbols, counter, extracted)),
186 then_expr: Box::new(rw(&e.then_expr, symbols, counter, extracted)),
187 else_ifs: e
188 .else_ifs
189 .iter()
190 .map(|ei| ElseIfExpression {
191 condition: Box::new(rw(&ei.condition, symbols, counter, extracted)),
192 then_expr: Box::new(rw(&ei.then_expr, symbols, counter, extracted)),
193 fragment: ei.fragment.clone(),
194 })
195 .collect(),
196 else_expr: e.else_expr.as_ref().map(|b| Box::new(rw(b, symbols, counter, extracted))),
197 fragment: e.fragment.clone(),
198 }),
199 Expression::FieldAccess(e) => Expression::FieldAccess(FieldAccessExpression {
200 object: Box::new(rw(&e.object, symbols, counter, extracted)),
201 field: e.field.clone(),
202 fragment: e.fragment.clone(),
203 }),
204
205 Expression::Tuple(e) => Expression::Tuple(TupleExpression {
206 expressions: rw_vec(&e.expressions, symbols, counter, extracted),
207 fragment: e.fragment.clone(),
208 }),
209 Expression::List(e) => Expression::List(ListExpression {
210 expressions: rw_vec(&e.expressions, symbols, counter, extracted),
211 fragment: e.fragment.clone(),
212 }),
213 Expression::Map(e) => Expression::Map(MapExpression {
214 expressions: rw_vec(&e.expressions, symbols, counter, extracted),
215 fragment: e.fragment.clone(),
216 }),
217 Expression::Extend(e) => Expression::Extend(ExtendExpression {
218 expressions: rw_vec(&e.expressions, symbols, counter, extracted),
219 fragment: e.fragment.clone(),
220 }),
221 Expression::Record(e) => Expression::Record(RecordExpression {
222 fields: e
223 .fields
224 .iter()
225 .map(|(name, expression)| {
226 (name.clone(), rewrite_expr(expression, symbols, counter, extracted))
227 })
228 .collect(),
229 fragment: e.fragment.clone(),
230 }),
231
232 Expression::Constant(_)
233 | Expression::Column(_)
234 | Expression::AccessSource(_)
235 | Expression::Parameter(_)
236 | Expression::Variable(_)
237 | Expression::Type(_)
238 | Expression::SumTypeConstructor(_)
239 | Expression::IsVariant(_) => expr.clone(),
240 }
241}